mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 05:11:02 +00:00
initial test to ensure auxiliary data is generated correctly
This commit is contained in:
@@ -39,11 +39,7 @@ impl<H, N> SharedAuthoritySet<H, N> {
|
|||||||
/// The genesis authority set.
|
/// The genesis authority set.
|
||||||
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
|
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
|
||||||
SharedAuthoritySet {
|
SharedAuthoritySet {
|
||||||
inner: Arc::new(RwLock::new(AuthoritySet {
|
inner: Arc::new(RwLock::new(AuthoritySet::genesis(initial)))
|
||||||
current_authorities: initial,
|
|
||||||
set_id: 0,
|
|
||||||
pending_changes: Vec::new(),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +87,15 @@ pub(crate) struct AuthoritySet<H, N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H, N> 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.
|
/// Get the current set id and a reference to the current authority set.
|
||||||
pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) {
|
pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) {
|
||||||
(self.set_id, &self.current_authorities[..])
|
(self.set_id, &self.current_authorities[..])
|
||||||
@@ -113,6 +118,12 @@ impl<H: Eq, N> AuthoritySet<H, N>
|
|||||||
|
|
||||||
self.pending_changes.insert(idx, pending);
|
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.
|
/// Get the earliest limit-block number, if any.
|
||||||
pub(crate) fn current_limit(&self) -> Option<N> {
|
pub(crate) fn current_limit(&self) -> Option<N> {
|
||||||
self.pending_changes.get(0).map(|change| change.effective_number().clone())
|
self.pending_changes.get(0).map(|change| change.effective_number().clone())
|
||||||
|
|||||||
@@ -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 super::*;
|
||||||
use network::test::{Block, Hash, TestNetFactory, Peer, PeersClient};
|
use network::test::{Block, Hash, TestNetFactory, Peer, PeersClient};
|
||||||
use network::import_queue::{PassThroughVerifier};
|
use network::import_queue::{PassThroughVerifier};
|
||||||
@@ -7,6 +25,10 @@ use tokio::runtime::current_thread;
|
|||||||
use keyring::Keyring;
|
use keyring::Keyring;
|
||||||
use client::BlockchainEvents;
|
use client::BlockchainEvents;
|
||||||
use test_client::{self, runtime::BlockNumber};
|
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 PeerData = Mutex<Option<LinkHalf<test_client::Backend, test_client::Executor, Block>>>;
|
||||||
type GrandpaPeer = Peer<PassThroughVerifier, PeerData>;
|
type GrandpaPeer = Peer<PassThroughVerifier, PeerData>;
|
||||||
@@ -135,14 +157,14 @@ impl Network for MessageRouting {
|
|||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
struct TestApi {
|
struct TestApi {
|
||||||
genesis_authorities: Vec<(AuthorityId, u64)>,
|
genesis_authorities: Vec<(AuthorityId, u64)>,
|
||||||
scheduled_changes: HashMap<BlockNumber, ScheduledChange<BlockNumber>>,
|
scheduled_changes: Arc<Mutex<HashMap<Hash, ScheduledChange<BlockNumber>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestApi {
|
impl TestApi {
|
||||||
fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self {
|
fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self {
|
||||||
TestApi {
|
TestApi {
|
||||||
genesis_authorities,
|
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
|
// we take only scheduled changes at given block number where there are no
|
||||||
// extrinsics.
|
// 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_GOSSIP_DURATION: Duration = Duration::from_millis(500);
|
||||||
const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
|
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]
|
#[test]
|
||||||
fn finalize_3_voters_no_observers() {
|
fn finalize_3_voters_no_observers() {
|
||||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||||
let voters: Vec<_> = peers.iter()
|
let voters = make_ids(peers);
|
||||||
.map(|key| AuthorityId(key.to_raw_public()))
|
|
||||||
.map(|id| (id, 1))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
||||||
net.peer(0).push_blocks(20, false);
|
net.peer(0).push_blocks(20, false);
|
||||||
@@ -229,10 +260,7 @@ fn finalize_3_voters_no_observers() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn finalize_3_voters_1_observer() {
|
fn finalize_3_voters_1_observer() {
|
||||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||||
let voters: Vec<_> = peers.iter()
|
let voters = make_ids(peers);
|
||||||
.map(|key| AuthorityId(key.to_raw_public()))
|
|
||||||
.map(|id| (id, 1))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 4);
|
let mut net = GrandpaTestNet::new(TestApi::new(voters), 4);
|
||||||
net.peer(0).push_blocks(20, false);
|
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();
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -236,14 +236,13 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
|
|||||||
|
|
||||||
/// Add blocks to the peer -- edit the block before adding
|
/// Add blocks to the peer -- edit the block before adding
|
||||||
pub fn generate_blocks<F>(&self, count: usize, origin: BlockOrigin, mut edit_block: F)
|
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;
|
use blocks::BlockData;
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
let mut builder = self.client.new_block().unwrap();
|
let builder = self.client.new_block().unwrap();
|
||||||
edit_block(&mut builder);
|
let block = edit_block(builder);
|
||||||
let block = builder.bake().unwrap();
|
|
||||||
let hash = block.header.hash();
|
let hash = block.header.hash();
|
||||||
trace!("Generating {}, (#{}, parent={})", hash, block.header.number, block.header.parent_hash);
|
trace!("Generating {}, (#{}, parent={})", hash, block.header.number, block.header.parent_hash);
|
||||||
let header = block.header.clone();
|
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) {
|
pub fn push_blocks(&self, count: usize, with_tx: bool) {
|
||||||
let mut nonce = 0;
|
let mut nonce = 0;
|
||||||
if with_tx {
|
if with_tx {
|
||||||
self.generate_blocks(count, BlockOrigin::File, |builder| {
|
self.generate_blocks(count, BlockOrigin::File, |mut builder| {
|
||||||
let transfer = Transfer {
|
let transfer = Transfer {
|
||||||
from: Keyring::Alice.to_raw_public().into(),
|
from: Keyring::Alice.to_raw_public().into(),
|
||||||
to: 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();
|
let signature = Keyring::from_raw_public(transfer.from.0).unwrap().sign(&transfer.encode()).into();
|
||||||
builder.push(Extrinsic { transfer, signature }).unwrap();
|
builder.push(Extrinsic { transfer, signature }).unwrap();
|
||||||
nonce = nonce + 1;
|
nonce = nonce + 1;
|
||||||
|
builder.bake().unwrap()
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.generate_blocks(count, BlockOrigin::File, |_| ());
|
self.generate_blocks(count, BlockOrigin::File, |builder| builder.bake().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user