mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-23 17:45:46 +00:00
Vstaging statement distribution omnibus (#1436)
in-progress PR adding new tests and solving bugs --------- Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> Co-authored-by: eskimor <eskimor@no-such-url.com> Co-authored-by: eskimor <eskimor@users.noreply.github.com> Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com>
This commit is contained in:
@@ -1797,6 +1797,7 @@ fn grid_statements_imported_to_backing() {
|
||||
|
||||
#[test]
|
||||
fn advertisements_rejected_from_incorrect_peers() {
|
||||
sp_tracing::try_init_simple();
|
||||
let validator_count = 6;
|
||||
let group_size = 3;
|
||||
let config = TestConfig {
|
||||
@@ -1831,12 +1832,12 @@ fn advertisements_rejected_from_incorrect_peers() {
|
||||
);
|
||||
let candidate_hash = candidate.hash();
|
||||
|
||||
let other_group_validators = state.group_validators(local_validator.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 target_group_validators = state.group_validators(local_validator.group_index, true);
|
||||
let other_group_validators = state.group_validators(other_group, true);
|
||||
let v_a = target_group_validators[0];
|
||||
let v_b = target_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.
|
||||
@@ -1911,10 +1912,11 @@ fn advertisements_rejected_from_incorrect_peers() {
|
||||
)
|
||||
.await;
|
||||
|
||||
// Message not expected from peers of our own group.
|
||||
assert_matches!(
|
||||
overseer.recv().await,
|
||||
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
|
||||
if p == peer_a && r == COST_UNEXPECTED_MANIFEST_DISALLOWED.into() => { }
|
||||
if p == peer_a && r == COST_UNEXPECTED_MANIFEST_PEER_UNKNOWN.into() => { }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1927,10 +1929,11 @@ fn advertisements_rejected_from_incorrect_peers() {
|
||||
)
|
||||
.await;
|
||||
|
||||
// Message not expected from peers of our own group.
|
||||
assert_matches!(
|
||||
overseer.recv().await,
|
||||
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
|
||||
if p == peer_b && r == COST_UNEXPECTED_MANIFEST_DISALLOWED.into() => { }
|
||||
if p == peer_b && r == COST_UNEXPECTED_MANIFEST_PEER_UNKNOWN.into() => { }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1306,6 +1306,208 @@ fn local_node_sanity_checks_incoming_requests() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_node_checks_that_peer_can_request_before_responding() {
|
||||
let config = TestConfig {
|
||||
validator_count: 20,
|
||||
group_size: 3,
|
||||
local_validator: true,
|
||||
async_backing_params: None,
|
||||
};
|
||||
|
||||
let relay_parent = Hash::repeat_byte(1);
|
||||
let peer_a = PeerId::random();
|
||||
let peer_b = PeerId::random();
|
||||
|
||||
test_harness(config, |mut state, mut overseer| async move {
|
||||
let local_validator = state.local.clone().unwrap();
|
||||
let local_para = ParaId::from(local_validator.group_index.0);
|
||||
|
||||
let test_leaf = state.make_dummy_leaf(relay_parent);
|
||||
|
||||
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();
|
||||
|
||||
// Peers A and B are in group and have relay parent in view.
|
||||
let other_group_validators = state.group_validators(local_validator.group_index, true);
|
||||
|
||||
connect_peer(
|
||||
&mut overseer,
|
||||
peer_a.clone(),
|
||||
Some(vec![state.discovery_id(other_group_validators[0])].into_iter().collect()),
|
||||
)
|
||||
.await;
|
||||
|
||||
connect_peer(
|
||||
&mut overseer,
|
||||
peer_b.clone(),
|
||||
Some(vec![state.discovery_id(other_group_validators[1])].into_iter().collect()),
|
||||
)
|
||||
.await;
|
||||
let peer_b_index = other_group_validators[1];
|
||||
|
||||
send_peer_view_change(&mut overseer, peer_a.clone(), view![relay_parent]).await;
|
||||
send_peer_view_change(&mut overseer, peer_b.clone(), view![relay_parent]).await;
|
||||
|
||||
// Finish setup
|
||||
activate_leaf(&mut overseer, &test_leaf, &state, true).await;
|
||||
|
||||
answer_expected_hypothetical_depth_request(
|
||||
&mut overseer,
|
||||
vec![],
|
||||
Some(relay_parent),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mask = StatementFilter::blank(state.config.group_size);
|
||||
|
||||
// Confirm candidate.
|
||||
let signed = state.sign_statement(
|
||||
local_validator.validator_index,
|
||||
CompactStatement::Seconded(candidate_hash),
|
||||
&SigningContext { session_index: 1, parent_hash: relay_parent },
|
||||
);
|
||||
let full_signed = signed
|
||||
.clone()
|
||||
.convert_to_superpayload(StatementWithPVD::Seconded(candidate.clone(), pvd.clone()))
|
||||
.unwrap();
|
||||
|
||||
overseer
|
||||
.send(FromOrchestra::Communication {
|
||||
msg: StatementDistributionMessage::Share(relay_parent, full_signed),
|
||||
})
|
||||
.await;
|
||||
|
||||
assert_matches!(
|
||||
overseer.recv().await,
|
||||
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(
|
||||
peers,
|
||||
Versioned::V2(protocol_v2::ValidationProtocol::StatementDistribution(
|
||||
protocol_v2::StatementDistributionMessage::Statement(
|
||||
r,
|
||||
s,
|
||||
)
|
||||
))
|
||||
)) => {
|
||||
assert_eq!(peers, vec![peer_a.clone(), peer_b.clone()]);
|
||||
assert_eq!(r, relay_parent);
|
||||
assert_eq!(s.unchecked_payload(), &CompactStatement::Seconded(candidate_hash));
|
||||
assert_eq!(s.unchecked_validator_index(), local_validator.validator_index);
|
||||
}
|
||||
);
|
||||
|
||||
answer_expected_hypothetical_depth_request(&mut overseer, vec![], None, false).await;
|
||||
|
||||
// Local node should respond to requests from peers in the same group
|
||||
// which appear to not have already seen the candidate
|
||||
{
|
||||
// Peer requests candidate and local responds
|
||||
let response = state
|
||||
.send_request(
|
||||
peer_a,
|
||||
request_v2::AttestedCandidateRequest {
|
||||
candidate_hash: candidate.hash(),
|
||||
mask: mask.clone(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.await;
|
||||
|
||||
let expected_statements = vec![signed.into_unchecked()];
|
||||
assert_matches!(response, full_response => {
|
||||
// Response is the same for vstaging.
|
||||
let request_v2::AttestedCandidateResponse { candidate_receipt, persisted_validation_data, statements } =
|
||||
request_v2::AttestedCandidateResponse::decode(
|
||||
&mut full_response.result.expect("We should have a proper answer").as_ref(),
|
||||
).expect("Decoding should work");
|
||||
assert_eq!(candidate_receipt, candidate);
|
||||
assert_eq!(persisted_validation_data, pvd);
|
||||
assert_eq!(statements, expected_statements);
|
||||
});
|
||||
}
|
||||
|
||||
// Local node should reject requests if the requester appears to know
|
||||
// the candidate (has sent them a Seconded statement)
|
||||
{
|
||||
let statement = state
|
||||
.sign_statement(
|
||||
peer_b_index,
|
||||
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_matches!(
|
||||
overseer.recv().await,
|
||||
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)))
|
||||
if p == peer_b && r == BENEFIT_VALID_STATEMENT_FIRST.into() => { }
|
||||
);
|
||||
|
||||
let response = state
|
||||
.send_request(
|
||||
peer_b,
|
||||
request_v2::AttestedCandidateRequest {
|
||||
candidate_hash: candidate.hash(),
|
||||
mask: mask.clone(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.await;
|
||||
|
||||
// Peer already knows about this candidate. Should reject.
|
||||
assert_matches!(
|
||||
response,
|
||||
RawOutgoingResponse {
|
||||
result,
|
||||
reputation_changes,
|
||||
sent_feedback
|
||||
} => {
|
||||
assert_matches!(result, Err(()));
|
||||
assert_eq!(reputation_changes, vec![COST_UNEXPECTED_REQUEST.into()]);
|
||||
assert_matches!(sent_feedback, None);
|
||||
}
|
||||
);
|
||||
|
||||
// Handling leftover statement distribution message
|
||||
assert_matches!(
|
||||
overseer.recv().await,
|
||||
AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage(
|
||||
peers,
|
||||
Versioned::V2(protocol_v2::ValidationProtocol::StatementDistribution(
|
||||
protocol_v2::StatementDistributionMessage::Statement(
|
||||
r,
|
||||
s,
|
||||
)
|
||||
))
|
||||
)) => {
|
||||
assert_eq!(peers, vec![peer_a.clone()]);
|
||||
assert_eq!(r, relay_parent);
|
||||
assert_eq!(s.unchecked_payload(), &CompactStatement::Seconded(candidate_hash));
|
||||
assert_eq!(s.unchecked_validator_index(), peer_b_index);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
overseer
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_node_respects_statement_mask() {
|
||||
let validator_count = 6;
|
||||
|
||||
Reference in New Issue
Block a user