mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 10:11:03 +00:00
grandpa: round catchup messages (#2801)
* grandpa: initial structure for catch up messages * grandpa: answer catch up requests * grandpa: inject catch up messages into global stream * grandpa: keep track of pending catch up request * grandpa: block catchup until all referenced blocks are imported * grandpa: unify catch up and commit streams * grandpa: simplify communication stream/sink types * grandpa: note gossip validator on catch up message import * grandpa: fix cost on catch up message validation * grandpa: check signatures on catch up messages * grandpa: clean up catch up request handling state * grandpa: adjust costs on invalid catch up requests * grandpa: release lock before pushing catch up message * grandpa: validate catch up request against peer view * grandpa: catch up docs * grandpa: fix tests * grandpa: until_imported: add tests for catch up messages * grandpa: add tests for catch up message gossip validation * grandpa: integrate HistoricalVotes changes * grandpa: add test for neighbor packet triggering catch up * grandpa: add test for full voter catch up * grandpa: depend on finality-grandpa 0.8 from crates * granda: use finality-grandpa test helpers * grandpa: add PSM cost for answering catch up requests * grandpa: code style fixes Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * grandpa: more trailing commas * grandpa: lower cost of invalid catch up requests near set change * grandpa: process catch up sending on import of neighbor message * grandpa: add comments on HistoricalVotes * grandpa: use finality-grandpa v0.8.1 from crates.io * grandpa: fix test compilation
This commit is contained in:
@@ -1181,6 +1181,7 @@ fn voter_persists_its_votes() {
|
||||
// sender is dropped the voter is stopped.
|
||||
{
|
||||
let net = net.clone();
|
||||
let client = client.clone();
|
||||
|
||||
let voter = future::loop_fn(voter_rx, move |rx| {
|
||||
let (_block_import, _, _, _, link) = net.lock().make_block_import(client.clone());
|
||||
@@ -1244,11 +1245,19 @@ fn voter_persists_its_votes() {
|
||||
local_key: Some(Arc::new(peers[1].clone().into())),
|
||||
name: Some(format!("peer#{}", 1)),
|
||||
};
|
||||
|
||||
let set_state = {
|
||||
let (_, _, _, _, link) = net.lock().make_block_import(client);
|
||||
let LinkHalf { persistent_data, .. } = link.lock().take().unwrap();
|
||||
let PersistentData { set_state, .. } = persistent_data;
|
||||
set_state
|
||||
};
|
||||
|
||||
let routing = MessageRouting::new(net.clone(), 1);
|
||||
let (network, routing_work) = communication::NetworkBridge::new(
|
||||
routing,
|
||||
config.clone(),
|
||||
None,
|
||||
set_state,
|
||||
Exit,
|
||||
);
|
||||
runtime.block_on(routing_work).unwrap();
|
||||
@@ -1480,3 +1489,111 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ
|
||||
if FORCE_CHANGE { 0 } else { 10 },
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn voter_catches_up_to_latest_round_when_behind() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob];
|
||||
let voters = make_ids(peers);
|
||||
|
||||
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
|
||||
net.peer(0).push_blocks(50, false);
|
||||
net.sync();
|
||||
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
let mut finality_notifications = Vec::new();
|
||||
|
||||
let mut runtime = current_thread::Runtime::new().unwrap();
|
||||
|
||||
let voter = |local_key, peer_id, link, net| -> Box<dyn Future<Item=(), Error=()> + Send> {
|
||||
let grandpa_params = GrandpaParams {
|
||||
config: Config {
|
||||
gossip_duration: TEST_GOSSIP_DURATION,
|
||||
justification_period: 32,
|
||||
local_key,
|
||||
name: Some(format!("peer#{}", peer_id)),
|
||||
},
|
||||
link: link,
|
||||
network: MessageRouting::new(net, peer_id),
|
||||
inherent_data_providers: InherentDataProviders::new(),
|
||||
on_exit: Exit,
|
||||
telemetry_on_connect: None,
|
||||
};
|
||||
|
||||
Box::new(run_grandpa_voter(grandpa_params).expect("all in order with client and network"))
|
||||
};
|
||||
|
||||
// spawn authorities
|
||||
for (peer_id, key) in peers.iter().enumerate() {
|
||||
let (client, link) = {
|
||||
let 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() < &50))
|
||||
.for_each(move |_| Ok(()))
|
||||
);
|
||||
|
||||
let voter = voter(Some(Arc::new((*key).into())), peer_id, link, net.clone());
|
||||
|
||||
runtime.spawn(voter);
|
||||
}
|
||||
|
||||
// wait for them to finalize block 50. since they'll vote on 3/4 of the
|
||||
// unfinalized chain it will take at least 4 rounds to do it.
|
||||
let wait_for_finality = ::futures::future::join_all(finality_notifications)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
|
||||
// spawn a new voter, it should be behind by at least 4 rounds and should be
|
||||
// able to catch up to the latest round
|
||||
let test = {
|
||||
let net = net.clone();
|
||||
let runtime = runtime.handle();
|
||||
|
||||
wait_for_finality.and_then(move |_| {
|
||||
let peer_id = 2;
|
||||
let (client, link) = {
|
||||
let 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,
|
||||
)
|
||||
};
|
||||
|
||||
let set_state = link.persistent_data.set_state.clone();
|
||||
|
||||
let wait = client.finality_notification_stream()
|
||||
.take_while(|n| Ok(n.header.number() < &50))
|
||||
.collect()
|
||||
.map(|_| set_state);
|
||||
|
||||
let voter = voter(None, peer_id, link, net);
|
||||
|
||||
runtime.spawn(voter).unwrap();
|
||||
|
||||
wait
|
||||
})
|
||||
.and_then(|set_state| {
|
||||
// the last completed round in the new voter is higher than 4
|
||||
// which means it caught up to the voters
|
||||
assert!(set_state.read().last_completed_round().number >= 4);
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
||||
let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
|
||||
.for_each(move |_| { net.lock().sync_without_disconnects(); Ok(()) })
|
||||
.map(|_| ())
|
||||
.map_err(|_| ());
|
||||
|
||||
let _ = runtime.block_on(test.select(drive_to_completion).map_err(|_| ())).unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user