mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 01:41:03 +00:00
GRANDPA finality proof draft (#1268)
* grandpa finality proof * prove GrandpaApi::grandpa_authorities using parent block + some docs * create justification when consensus data is changed * generate justifications periodically * test for ConsensusChanges
This commit is contained in:
committed by
Gav Wood
parent
677b79765b
commit
616716cb4b
@@ -25,6 +25,7 @@ use tokio::runtime::current_thread;
|
||||
use keyring::Keyring;
|
||||
use client::{
|
||||
BlockchainEvents, error::Result,
|
||||
blockchain::Backend as BlockchainBackend,
|
||||
runtime_api::{Core, RuntimeVersion, ApiExt, ConstructRuntimeApi, CallRuntimeAt},
|
||||
};
|
||||
use test_client::{self, runtime::BlockNumber};
|
||||
@@ -332,22 +333,7 @@ fn make_ids(keys: &[Keyring]) -> Vec<(Ed25519AuthorityId, u64)> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalize_3_voters_no_observers() {
|
||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
||||
net.peer(0).push_blocks(20, false);
|
||||
net.sync();
|
||||
|
||||
for i in 0..3 {
|
||||
assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 20,
|
||||
"Peer #{} failed to sync", i);
|
||||
}
|
||||
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
|
||||
fn run_to_completion(blocks: u64, net: Arc<Mutex<GrandpaTestNet>>, peers: &[Keyring]) {
|
||||
let mut finality_notifications = Vec::new();
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
|
||||
@@ -363,7 +349,7 @@ fn finalize_3_voters_no_observers() {
|
||||
};
|
||||
finality_notifications.push(
|
||||
client.finality_notification_stream()
|
||||
.take_while(|n| Ok(n.header.number() < &20))
|
||||
.take_while(|n| Ok(n.header.number() < &blocks))
|
||||
.for_each(|_| Ok(()))
|
||||
);
|
||||
fn assert_send<T: Send>(_: &T) { }
|
||||
@@ -371,6 +357,7 @@ fn finalize_3_voters_no_observers() {
|
||||
let voter = run_grandpa(
|
||||
Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
justification_period: 32,
|
||||
local_key: Some(Arc::new(key.clone().into())),
|
||||
name: Some(format!("peer#{}", peer_id)),
|
||||
},
|
||||
@@ -397,6 +384,28 @@ fn finalize_3_voters_no_observers() {
|
||||
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalize_3_voters_no_observers() {
|
||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
||||
net.peer(0).push_blocks(20, false);
|
||||
net.sync();
|
||||
|
||||
for i in 0..3 {
|
||||
assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 20,
|
||||
"Peer #{} failed to sync", i);
|
||||
}
|
||||
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
run_to_completion(20, net.clone(), peers);
|
||||
|
||||
// normally there's no justification for finalized blocks
|
||||
assert!(net.lock().peer(0).client().backend().blockchain().justification(BlockId::Number(20)).unwrap().is_none(),
|
||||
"Extra justification for block#1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finalize_3_voters_1_observer() {
|
||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||
@@ -432,6 +441,7 @@ fn finalize_3_voters_1_observer() {
|
||||
let voter = run_grandpa(
|
||||
Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
justification_period: 32,
|
||||
local_key,
|
||||
name: Some(format!("peer#{}", peer_id)),
|
||||
},
|
||||
@@ -589,6 +599,7 @@ fn transition_3_voters_twice_1_observer() {
|
||||
let voter = run_grandpa(
|
||||
Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
justification_period: 32,
|
||||
local_key,
|
||||
name: Some(format!("peer#{}", peer_id)),
|
||||
},
|
||||
@@ -616,3 +627,59 @@ fn transition_3_voters_twice_1_observer() {
|
||||
|
||||
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn justification_is_emitted_when_consensus_data_changes() {
|
||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3);
|
||||
|
||||
// import block#1 WITH consensus data change
|
||||
let new_authorities = vec![Ed25519AuthorityId::from([42; 32])];
|
||||
net.peer(0).push_authorities_change_block(new_authorities);
|
||||
net.sync();
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
run_to_completion(1, net.clone(), peers);
|
||||
|
||||
// ... and check that there's no justification for block#1
|
||||
assert!(net.lock().peer(0).client().backend().blockchain().justification(BlockId::Number(1)).unwrap().is_some(),
|
||||
"Missing justification for block#1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn justification_is_generated_periodically() {
|
||||
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
||||
net.peer(0).push_blocks(32, false);
|
||||
net.sync();
|
||||
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
run_to_completion(32, net.clone(), peers);
|
||||
|
||||
// when block#32 (justification_period) is finalized, justification
|
||||
// is required => generated
|
||||
for i in 0..3 {
|
||||
assert!(net.lock().peer(i).client().backend().blockchain()
|
||||
.justification(BlockId::Number(32)).unwrap().is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consensus_changes_works() {
|
||||
let mut changes = ConsensusChanges::<H256, u64>::empty();
|
||||
|
||||
// pending changes are not finalized
|
||||
changes.note_change((10, 1.into()));
|
||||
assert_eq!(changes.finalize((5, 5.into()), |_| Ok(None)).unwrap(), (false, false));
|
||||
|
||||
// no change is selected from competing pending changes
|
||||
changes.note_change((1, 1.into()));
|
||||
changes.note_change((1, 101.into()));
|
||||
assert_eq!(changes.finalize((10, 10.into()), |_| Ok(Some(1001.into()))).unwrap(), (true, false));
|
||||
|
||||
// change is selected from competing pending changes
|
||||
changes.note_change((1, 1.into()));
|
||||
changes.note_change((1, 101.into()));
|
||||
assert_eq!(changes.finalize((10, 10.into()), |_| Ok(Some(1.into()))).unwrap(), (true, true));
|
||||
}
|
||||
Reference in New Issue
Block a user