statement-distribution: Add tests for incoming acknowledgements (#2498)

This commit is contained in:
Marcin S
2023-12-05 12:15:38 +01:00
committed by GitHub
parent a310df263d
commit f240e02557
5 changed files with 594 additions and 160 deletions
@@ -44,6 +44,8 @@ fn backed_candidate_leads_to_advertisement() {
let local_group_index = local_validator.group_index.unwrap();
let local_para = ParaId::from(local_group_index.0);
let other_group = next_group_index(local_group_index, validator_count, group_size);
let test_leaf = state.make_dummy_leaf(relay_parent);
let (candidate, pvd) = make_candidate(
@@ -56,13 +58,12 @@ fn backed_candidate_leads_to_advertisement() {
);
let candidate_hash = candidate.hash();
let other_group_validators = state.group_validators(local_group_index, true);
let target_group_validators =
state.group_validators((local_group_index.0 + 1).into(), true);
let v_a = other_group_validators[0];
let v_b = other_group_validators[1];
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let local_group_validators = state.group_validators(local_group_index, true);
let other_group_validators = state.group_validators(other_group, true);
let v_a = local_group_validators[0];
let v_b = local_group_validators[1];
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer A is in group, has relay parent in view.
// peer B is in group, has no relay parent in view.
@@ -274,12 +275,12 @@ fn received_advertisement_before_confirmation_leads_to_request() {
);
let candidate_hash = candidate.hash();
let other_group_validators = state.group_validators(local_group_index, true);
let target_group_validators = state.group_validators(other_group, true);
let v_a = other_group_validators[0];
let v_b = other_group_validators[1];
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let local_group_validators = state.group_validators(local_group_index, true);
let other_group_validators = state.group_validators(other_group, true);
let v_a = local_group_validators[0];
let v_b = local_group_validators[1];
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer A is in group, has relay parent in view.
// peer B is in group, has no relay parent in view.
@@ -429,19 +430,33 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
async_backing_params: None,
};
let relay_parent = Hash::repeat_byte(1);
let peer_c = PeerId::random();
let peer_d = PeerId::random();
let peer_e = PeerId::random();
test_harness(config, |state, mut overseer| async move {
let local_validator = state.local.clone().unwrap();
let local_group_index = local_validator.group_index.unwrap();
let peers_to_connect = [
TestPeerToConnect { local: true, relay_parent_in_view: false },
TestPeerToConnect { local: true, relay_parent_in_view: false },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: true },
];
let other_group = next_group_index(local_group_index, validator_count, group_size);
let other_para = ParaId::from(other_group.0);
let test_leaf = state.make_dummy_leaf(relay_parent);
let TestSetupInfo {
other_group,
other_para,
relay_parent,
test_leaf,
peers,
validators,
..
} = setup_test_and_connect_peers(
&state,
&mut overseer,
validator_count,
group_size,
&peers_to_connect,
)
.await;
let [_, _, peer_c, peer_d, _] = peers[..] else { panic!() };
let [_, _, v_c, v_d, v_e] = validators[..] else { panic!() };
let (candidate, pvd) = make_candidate(
relay_parent,
@@ -453,52 +468,6 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let v_e = target_group_validators[2];
// Connect C, D, E
{
connect_peer(
&mut overseer,
peer_c.clone(),
Some(vec![state.discovery_id(v_c)].into_iter().collect()),
)
.await;
connect_peer(
&mut overseer,
peer_d.clone(),
Some(vec![state.discovery_id(v_d)].into_iter().collect()),
)
.await;
connect_peer(
&mut overseer,
peer_e.clone(),
Some(vec![state.discovery_id(v_e)].into_iter().collect()),
)
.await;
send_peer_view_change(&mut overseer, peer_c.clone(), view![relay_parent]).await;
send_peer_view_change(&mut overseer, peer_d.clone(), view![relay_parent]).await;
send_peer_view_change(&mut overseer, peer_e.clone(), view![relay_parent]).await;
}
activate_leaf(&mut overseer, &test_leaf, &state, true).await;
answer_expected_hypothetical_depth_request(
&mut overseer,
vec![],
Some(relay_parent),
false,
)
.await;
// Send gossip topology.
send_new_topology(&mut overseer, state.make_dummy_topology()).await;
let manifest = BackedCandidateManifest {
relay_parent,
candidate_hash,
@@ -530,14 +499,7 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
// Receive an advertisement from C.
{
send_peer_message(
&mut overseer,
peer_c.clone(),
protocol_v2::StatementDistributionMessage::BackedCandidateManifest(
manifest.clone(),
),
)
.await;
send_manifest_from_peer(&mut overseer, peer_c, manifest.clone()).await;
// Should send a request to C.
let statements = vec![
@@ -563,37 +525,16 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
)
.await;
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
if p == peer_c && r == BENEFIT_VALID_STATEMENT.into()
);
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
if p == peer_c && r == BENEFIT_VALID_STATEMENT.into()
);
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
if p == peer_c && r == BENEFIT_VALID_STATEMENT.into()
);
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
if p == peer_c && r == BENEFIT_VALID_RESPONSE.into()
);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_RESPONSE);
answer_expected_hypothetical_depth_request(&mut overseer, vec![], None, false).await;
}
// Receive Backed message.
overseer
.send(FromOrchestra::Communication {
msg: StatementDistributionMessage::Backed(candidate_hash),
})
.await;
send_backed_message(&mut overseer, candidate_hash).await;
// Should send an acknowledgement back to C.
{
@@ -625,14 +566,7 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
// Receive a manifest about the same candidate from peer D.
{
send_peer_message(
&mut overseer,
peer_d.clone(),
protocol_v2::StatementDistributionMessage::BackedCandidateManifest(
manifest.clone(),
),
)
.await;
send_manifest_from_peer(&mut overseer, peer_d, manifest.clone()).await;
let expected_ack = BackedCandidateAcknowledgement {
candidate_hash,
@@ -665,6 +599,360 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() {
});
}
#[test]
fn receive_ack_for_unconfirmed_candidate() {
let validator_count = 6;
let group_size = 3;
let config = TestConfig {
validator_count,
group_size,
local_validator: LocalRole::Validator,
async_backing_params: None,
};
test_harness(config, |state, mut overseer| async move {
let peers_to_connect = [
TestPeerToConnect { local: true, relay_parent_in_view: true },
TestPeerToConnect { local: true, relay_parent_in_view: false },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: false },
];
let TestSetupInfo { local_para, relay_parent, test_leaf, peers, .. } =
setup_test_and_connect_peers(
&state,
&mut overseer,
validator_count,
group_size,
&peers_to_connect,
)
.await;
let [_, _, peer_c, _] = peers[..] else { panic!() };
let (candidate, _pvd) = make_candidate(
relay_parent,
1,
local_para,
test_leaf.para_data(local_para).head_data.clone(),
vec![4, 5, 6].into(),
Hash::repeat_byte(42).into(),
);
let candidate_hash = candidate.hash();
let ack = BackedCandidateAcknowledgement {
candidate_hash,
statement_knowledge: StatementFilter {
seconded_in_group: bitvec::bitvec![u8, Lsb0; 1, 1, 1],
validated_in_group: bitvec::bitvec![u8, Lsb0; 0, 0, 0],
},
};
// Receive an acknowledgement from a peer before the candidate is confirmed.
send_ack_from_peer(&mut overseer, peer_c, ack.clone()).await;
assert_peer_reported!(
&mut overseer,
peer_c,
COST_UNEXPECTED_ACKNOWLEDGEMENT_UNKNOWN_CANDIDATE,
);
overseer
});
}
// Test receiving unexpected and expected acknowledgements for a locally confirmed candidate.
#[test]
fn received_acknowledgements_for_locally_confirmed() {
let validator_count = 6;
let group_size = 3;
let config = TestConfig {
validator_count,
group_size,
local_validator: LocalRole::Validator,
async_backing_params: None,
};
test_harness(config, |state, mut overseer| async move {
let peers_to_connect = [
TestPeerToConnect { local: true, relay_parent_in_view: true },
TestPeerToConnect { local: true, relay_parent_in_view: false },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: false },
];
let TestSetupInfo {
local_validator,
local_group,
local_para,
relay_parent,
test_leaf,
peers,
validators,
..
} = setup_test_and_connect_peers(
&state,
&mut overseer,
validator_count,
group_size,
&peers_to_connect,
)
.await;
let [peer_a, peer_b, peer_c, peer_d] = peers[..] else { panic!() };
let [_, v_b, _, _] = validators[..] else { panic!() };
let (candidate, pvd) = make_candidate(
relay_parent,
1,
local_para,
test_leaf.para_data(local_para).head_data.clone(),
vec![4, 5, 6].into(),
Hash::repeat_byte(42).into(),
);
let candidate_hash = candidate.hash();
let ack = BackedCandidateAcknowledgement {
candidate_hash,
statement_knowledge: StatementFilter {
seconded_in_group: bitvec::bitvec![u8, Lsb0; 1, 1, 1],
validated_in_group: bitvec::bitvec![u8, Lsb0; 0, 0, 0],
},
};
// Confirm the candidate locally so that we don't send out requests.
{
let statement = state
.sign_full_statement(
local_validator.validator_index,
Statement::Seconded(candidate.clone()),
&SigningContext { parent_hash: relay_parent, session_index: 1 },
pvd.clone(),
)
.clone();
send_share_message(&mut overseer, relay_parent, statement).await;
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a]
);
answer_expected_hypothetical_depth_request(&mut overseer, vec![], None, false).await;
}
// Receive an unexpected acknowledgement from peer D.
send_ack_from_peer(&mut overseer, peer_d, ack.clone()).await;
assert_peer_reported!(&mut overseer, peer_d, COST_UNEXPECTED_MANIFEST_DISALLOWED);
// Send statement from peer B.
{
let statement = state
.sign_statement(
v_b,
CompactStatement::Seconded(candidate_hash),
&SigningContext { parent_hash: relay_parent, session_index: 1 },
)
.as_unchecked()
.clone();
send_peer_message(
&mut overseer,
peer_b.clone(),
protocol_v2::StatementDistributionMessage::Statement(relay_parent, statement),
)
.await;
assert_peer_reported!(&mut overseer, peer_b, BENEFIT_VALID_STATEMENT_FIRST);
assert_matches!(
overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(peers, _)) if peers == vec![peer_a]
);
}
// Send Backed notification.
{
send_backed_message(&mut overseer, candidate_hash).await;
// We should send out a manifest.
assert_matches!(
overseer.recv().await,
AllMessages:: NetworkBridgeTx(
NetworkBridgeTxMessage::SendValidationMessage(
peers,
Versioned::V2(
protocol_v2::ValidationProtocol::StatementDistribution(
protocol_v2::StatementDistributionMessage::BackedCandidateManifest(manifest),
),
),
)
) => {
assert_eq!(peers, vec![peer_c]);
assert_eq!(manifest, BackedCandidateManifest {
relay_parent,
candidate_hash,
group_index: local_group,
para_id: local_para,
parent_head_data_hash: pvd.parent_head.hash(),
statement_knowledge: StatementFilter {
seconded_in_group: bitvec::bitvec![u8, Lsb0; 0, 1, 1],
validated_in_group: bitvec::bitvec![u8, Lsb0; 0, 0, 0],
},
});
}
);
answer_expected_hypothetical_depth_request(&mut overseer, vec![], None, false).await;
}
// Receive an unexpected acknowledgement from peer D.
//
// It still shouldn't know this manifest.
send_ack_from_peer(&mut overseer, peer_d, ack.clone()).await;
assert_peer_reported!(&mut overseer, peer_d, COST_UNEXPECTED_MANIFEST_DISALLOWED);
// Receive an acknowledgement from peer C.
//
// It's OK, we know they know it because we sent them a manifest.
send_ack_from_peer(&mut overseer, peer_c, ack.clone()).await;
// What happens if we get another valid ack?
send_ack_from_peer(&mut overseer, peer_c, ack.clone()).await;
overseer
});
}
// Test receiving unexpected acknowledgements for a candidate confirmed in a different group.
#[test]
fn received_acknowledgements_for_externally_confirmed() {
let validator_count = 6;
let group_size = 3;
let config = TestConfig {
validator_count,
group_size,
local_validator: LocalRole::Validator,
async_backing_params: None,
};
test_harness(config, |state, mut overseer| async move {
let peers_to_connect = [
TestPeerToConnect { local: true, relay_parent_in_view: true },
TestPeerToConnect { local: true, relay_parent_in_view: false },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: true },
TestPeerToConnect { local: false, relay_parent_in_view: true },
];
let TestSetupInfo {
other_group,
other_para,
relay_parent,
test_leaf,
peers,
validators,
..
} = setup_test_and_connect_peers(
&state,
&mut overseer,
validator_count,
group_size,
&peers_to_connect,
)
.await;
let [peer_a, _, peer_c, peer_d, _] = peers[..] else { panic!() };
let [_, _, v_c, v_d, v_e] = validators[..] else { panic!() };
let (candidate, pvd) = make_candidate(
relay_parent,
1,
other_para,
test_leaf.para_data(other_para).head_data.clone(),
vec![4, 5, 6].into(),
Hash::repeat_byte(42).into(),
);
let candidate_hash = candidate.hash();
let manifest = BackedCandidateManifest {
relay_parent,
candidate_hash,
group_index: other_group,
para_id: other_para,
parent_head_data_hash: pvd.parent_head.hash(),
statement_knowledge: StatementFilter {
seconded_in_group: bitvec::bitvec![u8, Lsb0; 0, 1, 1],
validated_in_group: bitvec::bitvec![u8, Lsb0; 0, 0, 0],
},
};
let statement_c = state
.sign_statement(
v_c,
CompactStatement::Seconded(candidate_hash),
&SigningContext { parent_hash: relay_parent, session_index: 1 },
)
.as_unchecked()
.clone();
let statement_d = state
.sign_statement(
v_d,
CompactStatement::Seconded(candidate_hash),
&SigningContext { parent_hash: relay_parent, session_index: 1 },
)
.as_unchecked()
.clone();
// Receive an advertisement from C, confirming the candidate.
{
send_manifest_from_peer(&mut overseer, peer_c, manifest.clone()).await;
// Should send a request to C.
let statements = vec![
statement_c.clone(),
statement_d.clone(),
state
.sign_statement(
v_e,
CompactStatement::Seconded(candidate_hash),
&SigningContext { parent_hash: relay_parent, session_index: 1 },
)
.as_unchecked()
.clone(),
];
handle_sent_request(
&mut overseer,
peer_c,
candidate_hash,
StatementFilter::blank(group_size),
candidate.clone(),
pvd.clone(),
statements,
)
.await;
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_STATEMENT);
assert_peer_reported!(&mut overseer, peer_c, BENEFIT_VALID_RESPONSE);
answer_expected_hypothetical_depth_request(&mut overseer, vec![], None, false).await;
}
let ack = BackedCandidateAcknowledgement {
candidate_hash,
statement_knowledge: StatementFilter {
seconded_in_group: bitvec::bitvec![u8, Lsb0; 1, 1, 1],
validated_in_group: bitvec::bitvec![u8, Lsb0; 0, 0, 0],
},
};
// Receive an unexpected acknowledgement from peer D.
send_ack_from_peer(&mut overseer, peer_d, ack.clone()).await;
assert_peer_reported!(&mut overseer, peer_d, COST_UNEXPECTED_MANIFEST_PEER_UNKNOWN);
// Receive an unexpected acknowledgement from peer A.
send_ack_from_peer(&mut overseer, peer_a, ack.clone()).await;
assert_peer_reported!(&mut overseer, peer_a, COST_UNEXPECTED_MANIFEST_DISALLOWED);
overseer
});
}
// Received advertisement after confirmation but before backing leads to nothing.
#[test]
fn received_advertisement_after_confirmation_before_backing() {
@@ -701,10 +989,10 @@ fn received_advertisement_after_confirmation_before_backing() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let v_e = target_group_validators[2];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
let v_e = other_group_validators[2];
// Connect C, D, E
{
@@ -887,10 +1175,10 @@ fn additional_statements_are_shared_after_manifest_exchange() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let v_e = target_group_validators[2];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
let v_e = other_group_validators[2];
// Connect C, D, E
{
@@ -1183,13 +1471,12 @@ fn advertisement_sent_when_peer_enters_relay_parent_view() {
);
let candidate_hash = candidate.hash();
let other_group_validators = state.group_validators(local_group_index, true);
let target_group_validators =
state.group_validators((local_group_index.0 + 1).into(), true);
let v_a = other_group_validators[0];
let v_b = other_group_validators[1];
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let local_group_validators = state.group_validators(local_group_index, true);
let other_group_validators = state.group_validators((local_group_index.0 + 1).into(), true);
let v_a = local_group_validators[0];
let v_b = local_group_validators[1];
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer A is in group, has relay parent in view.
// peer B is in group, has no relay parent in view.
@@ -1406,13 +1693,12 @@ fn advertisement_not_re_sent_when_peer_re_enters_view() {
);
let candidate_hash = candidate.hash();
let other_group_validators = state.group_validators(local_group_index, true);
let target_group_validators =
state.group_validators((local_group_index.0 + 1).into(), true);
let v_a = other_group_validators[0];
let v_b = other_group_validators[1];
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let local_group_validators = state.group_validators(local_group_index, true);
let other_group_validators = state.group_validators((local_group_index.0 + 1).into(), true);
let v_a = local_group_validators[0];
let v_b = local_group_validators[1];
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer A is in group, has relay parent in view.
// peer B is in group, has no relay parent in view.
@@ -1630,10 +1916,10 @@ fn grid_statements_imported_to_backing() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let v_e = target_group_validators[2];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
let v_e = other_group_validators[2];
// Connect C, D, E
{
@@ -1835,12 +2121,12 @@ fn advertisements_rejected_from_incorrect_peers() {
);
let candidate_hash = candidate.hash();
let other_group_validators = state.group_validators(local_group_index, true);
let target_group_validators = state.group_validators(other_group, true);
let v_a = other_group_validators[0];
let v_b = other_group_validators[1];
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let local_group_validators = state.group_validators(local_group_index, true);
let other_group_validators = state.group_validators(other_group, true);
let v_a = local_group_validators[0];
let v_b = local_group_validators[1];
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer A is in group, has relay parent in view.
// peer B is in group, has no relay parent in view.
@@ -1979,9 +2265,9 @@ fn manifest_rejected_with_unknown_relay_parent() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer C is not in group, has relay parent in view.
// peer D is not in group, has no relay parent in view.
@@ -2081,9 +2367,9 @@ fn manifest_rejected_when_not_a_validator() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer C is not in group, has relay parent in view.
// peer D is not in group, has no relay parent in view.
@@ -2188,9 +2474,9 @@ fn manifest_rejected_when_group_does_not_match_para() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
// peer C is not in group, has relay parent in view.
// peer D is not in group, has no relay parent in view.
@@ -2294,10 +2580,10 @@ fn peer_reported_for_advertisement_conflicting_with_confirmed_candidate() {
);
let candidate_hash = candidate.hash();
let target_group_validators = state.group_validators(other_group, true);
let v_c = target_group_validators[0];
let v_d = target_group_validators[1];
let v_e = target_group_validators[2];
let other_group_validators = state.group_validators(other_group, true);
let v_c = other_group_validators[0];
let v_d = other_group_validators[1];
let v_e = other_group_validators[2];
// Connect C, D, E
{
@@ -21,6 +21,7 @@ use crate::*;
use polkadot_node_network_protocol::{
grid_topology::TopologyPeerInfo,
request_response::{outgoing::Recipient, ReqProtocolNames},
v2::{BackedCandidateAcknowledgement, BackedCandidateManifest},
view, ObservedRole,
};
use polkadot_node_primitives::Statement;
@@ -377,6 +378,95 @@ impl TestLeaf {
}
}
struct TestSetupInfo {
local_validator: TestLocalValidator,
local_group: GroupIndex,
local_para: ParaId,
other_group: GroupIndex,
other_para: ParaId,
relay_parent: Hash,
test_leaf: TestLeaf,
peers: Vec<PeerId>,
validators: Vec<ValidatorIndex>,
}
struct TestPeerToConnect {
local: bool,
relay_parent_in_view: bool,
}
// TODO: Generalize, use in more places.
/// Sets up some test info that is common to most tests, and connects the requested peers.
async fn setup_test_and_connect_peers(
state: &TestState,
overseer: &mut VirtualOverseer,
validator_count: usize,
group_size: usize,
peers_to_connect: &[TestPeerToConnect],
) -> TestSetupInfo {
let local_validator = state.local.clone().unwrap();
let local_group = local_validator.group_index.unwrap();
let local_para = ParaId::from(local_group.0);
let other_group = next_group_index(local_group, validator_count, group_size);
let other_para = ParaId::from(other_group.0);
let relay_parent = Hash::repeat_byte(1);
let test_leaf = state.make_dummy_leaf(relay_parent);
// Because we are testing grid mod, the "target" group (the one we communicate with) is usually
// other_group, a non-local group.
//
// TODO: change based on `LocalRole`?
let local_group_validators = state.group_validators(local_group, true);
let other_group_validators = state.group_validators(other_group, true);
let mut peers = vec![];
let mut validators = vec![];
let mut local_group_idx = 0;
let mut other_group_idx = 0;
for peer_to_connect in peers_to_connect {
let peer = PeerId::random();
peers.push(peer);
let v = if peer_to_connect.local {
let v = local_group_validators[local_group_idx];
local_group_idx += 1;
v
} else {
let v = other_group_validators[other_group_idx];
other_group_idx += 1;
v
};
validators.push(v);
connect_peer(overseer, peer, Some(vec![state.discovery_id(v)].into_iter().collect())).await;
if peer_to_connect.relay_parent_in_view {
send_peer_view_change(overseer, peer.clone(), view![relay_parent]).await;
}
}
activate_leaf(overseer, &test_leaf, &state, true).await;
answer_expected_hypothetical_depth_request(overseer, vec![], Some(relay_parent), false).await;
// Send gossip topology.
send_new_topology(overseer, state.make_dummy_topology()).await;
TestSetupInfo {
local_validator,
local_group,
local_para,
other_group,
other_para,
test_leaf,
relay_parent,
peers,
validators,
}
}
async fn activate_leaf(
virtual_overseer: &mut VirtualOverseer,
leaf: &TestLeaf,
@@ -547,6 +637,66 @@ async fn answer_expected_hypothetical_depth_request(
)
}
#[macro_export]
macro_rules! assert_peer_reported {
($virtual_overseer:expr, $peer_id:expr, $rep_change:expr $(,)*) => {
assert_matches!(
$virtual_overseer.recv().await,
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
if p == $peer_id && r == $rep_change.into()
);
}
}
async fn send_share_message(
virtual_overseer: &mut VirtualOverseer,
relay_parent: Hash,
statement: SignedFullStatementWithPVD,
) {
virtual_overseer
.send(FromOrchestra::Communication {
msg: StatementDistributionMessage::Share(relay_parent, statement),
})
.await;
}
async fn send_backed_message(
virtual_overseer: &mut VirtualOverseer,
candidate_hash: CandidateHash,
) {
virtual_overseer
.send(FromOrchestra::Communication {
msg: StatementDistributionMessage::Backed(candidate_hash),
})
.await;
}
async fn send_manifest_from_peer(
virtual_overseer: &mut VirtualOverseer,
peer_id: PeerId,
manifest: BackedCandidateManifest,
) {
send_peer_message(
virtual_overseer,
peer_id,
protocol_v2::StatementDistributionMessage::BackedCandidateManifest(manifest),
)
.await;
}
async fn send_ack_from_peer(
virtual_overseer: &mut VirtualOverseer,
peer_id: PeerId,
ack: BackedCandidateAcknowledgement,
) {
send_peer_message(
virtual_overseer,
peer_id,
protocol_v2::StatementDistributionMessage::BackedCandidateKnown(ack),
)
.await;
}
fn validator_pubkeys(val_ids: &[ValidatorPair]) -> IndexedVec<ValidatorIndex, ValidatorId> {
val_ids.iter().map(|v| v.public().into()).collect()
}