Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit b601bbc

Browse files
committed
Second multiple candidates per relay parent test
1 parent b8b6ca0 commit b601bbc

File tree

2 files changed

+132
-1
lines changed

2 files changed

+132
-1
lines changed

node/core/backing/src/tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ fn make_erasure_root(test: &TestState, pov: PoV) -> Hash {
197197
erasure_coding::branches(&chunks).root()
198198
}
199199

200-
#[derive(Default)]
200+
#[derive(Default, Clone)]
201201
struct TestCandidateBuilder {
202202
para_id: ParaId,
203203
head_data: HeadData,

node/core/backing/src/tests/prospective_parachains.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,3 +787,134 @@ fn prospective_parachains_reject_candidate() {
787787
virtual_overseer
788788
});
789789
}
790+
791+
// Test that a validator can second multiple candidates per single relay parent.
792+
#[test]
793+
fn second_multiple_candidates_per_relay_parent() {
794+
let test_state = TestState::default();
795+
test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move {
796+
// Candidate `a` is seconded in a parent of the activated `leaf`.
797+
const LEAF_BLOCK_NUMBER: BlockNumber = 100;
798+
const LEAF_DEPTH: BlockNumber = 3;
799+
let para_id = test_state.chain_ids[0];
800+
801+
let leaf_hash = Hash::from_low_u64_be(130);
802+
let leaf_parent = get_parent_hash(leaf_hash);
803+
let leaf_grandparent = get_parent_hash(leaf_parent);
804+
let activated = ActivatedLeaf {
805+
hash: leaf_hash,
806+
number: LEAF_BLOCK_NUMBER,
807+
status: LeafStatus::Fresh,
808+
span: Arc::new(jaeger::Span::Disabled),
809+
};
810+
let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_DEPTH)];
811+
let test_leaf_a = TestLeaf { activated, min_relay_parents };
812+
813+
activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await;
814+
815+
let pov = PoV { block_data: BlockData(vec![42, 43, 44]) };
816+
let pvd = dummy_pvd();
817+
let validation_code = ValidationCode(vec![1, 2, 3]);
818+
819+
let expected_head_data = test_state.head_data.get(&para_id).unwrap();
820+
821+
let pov_hash = pov.hash();
822+
let candidate_a = TestCandidateBuilder {
823+
para_id,
824+
relay_parent: leaf_parent,
825+
pov_hash,
826+
head_data: expected_head_data.clone(),
827+
erasure_root: make_erasure_root(&test_state, pov.clone()),
828+
persisted_validation_data_hash: pvd.hash(),
829+
validation_code: validation_code.0.clone(),
830+
..Default::default()
831+
};
832+
let mut candidate_b = candidate_a.clone();
833+
candidate_b.relay_parent = leaf_grandparent;
834+
835+
// With depths.
836+
let candidate_a = (candidate_a.build(), 1);
837+
let candidate_b = (candidate_b.build(), 2);
838+
839+
for candidate in &[candidate_a, candidate_b] {
840+
let (candidate, depth) = candidate;
841+
let second = CandidateBackingMessage::Second(
842+
leaf_hash,
843+
candidate.to_plain(),
844+
pvd.clone(),
845+
pov.clone(),
846+
);
847+
848+
virtual_overseer.send(FromOverseer::Communication { msg: second }).await;
849+
850+
assert_validate_seconded_candidate(
851+
&mut virtual_overseer,
852+
candidate.descriptor().relay_parent,
853+
&candidate,
854+
&pov,
855+
&pvd,
856+
&validation_code,
857+
expected_head_data,
858+
)
859+
.await;
860+
861+
// `seconding_sanity_check`
862+
let expected_request_a = vec![(
863+
HypotheticalDepthRequest {
864+
candidate_hash: candidate.hash(),
865+
candidate_para: para_id,
866+
parent_head_data_hash: pvd.parent_head.hash(),
867+
candidate_relay_parent: candidate.descriptor().relay_parent,
868+
fragment_tree_relay_parent: leaf_hash,
869+
},
870+
vec![*depth],
871+
)];
872+
assert_hypothetical_depth_requests(&mut virtual_overseer, expected_request_a.clone())
873+
.await;
874+
875+
// Prospective parachains are notified.
876+
assert_matches!(
877+
virtual_overseer.recv().await,
878+
AllMessages::ProspectiveParachains(
879+
ProspectiveParachainsMessage::CandidateSeconded(
880+
candidate_para,
881+
candidate_receipt,
882+
_pvd,
883+
tx,
884+
),
885+
) if &candidate_receipt == candidate && candidate_para == para_id && pvd == _pvd => {
886+
// Any non-empty response will do.
887+
tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap();
888+
}
889+
);
890+
891+
test_dispute_coordinator_notifications(
892+
&mut virtual_overseer,
893+
candidate.hash(),
894+
test_state.session(),
895+
vec![ValidatorIndex(0)],
896+
)
897+
.await;
898+
899+
assert_matches!(
900+
virtual_overseer.recv().await,
901+
AllMessages::StatementDistribution(
902+
StatementDistributionMessage::Share(
903+
parent_hash,
904+
_signed_statement,
905+
)
906+
) if parent_hash == candidate.descriptor().relay_parent => {}
907+
);
908+
909+
assert_matches!(
910+
virtual_overseer.recv().await,
911+
AllMessages::CollatorProtocol(CollatorProtocolMessage::Seconded(hash, statement)) => {
912+
assert_eq!(candidate.descriptor().relay_parent, hash);
913+
assert_matches!(statement.payload(), Statement::Seconded(_));
914+
}
915+
);
916+
}
917+
918+
virtual_overseer
919+
});
920+
}

0 commit comments

Comments
 (0)