From 154a6650ecc349d470b0c3c69149b788787acd0a Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Mon, 13 Jun 2022 16:18:35 +0300 Subject: [PATCH] Second multiple candidates per relay parent test --- node/core/backing/src/tests/mod.rs | 2 +- .../src/tests/prospective_parachains.rs | 132 ++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/node/core/backing/src/tests/mod.rs b/node/core/backing/src/tests/mod.rs index 0f0a319f5bf6..e6b02ae0e3e2 100644 --- a/node/core/backing/src/tests/mod.rs +++ b/node/core/backing/src/tests/mod.rs @@ -197,7 +197,7 @@ fn make_erasure_root(test: &TestState, pov: PoV) -> Hash { erasure_coding::branches(&chunks).root() } -#[derive(Default)] +#[derive(Default, Clone)] struct TestCandidateBuilder { para_id: ParaId, head_data: HeadData, diff --git a/node/core/backing/src/tests/prospective_parachains.rs b/node/core/backing/src/tests/prospective_parachains.rs index b75e4152224d..911ff3111a46 100644 --- a/node/core/backing/src/tests/prospective_parachains.rs +++ b/node/core/backing/src/tests/prospective_parachains.rs @@ -787,3 +787,135 @@ fn prospective_parachains_reject_candidate() { virtual_overseer }); } + +// Test that a seconded candidate which is not approved by prospective parachains +// subsystem doesn't change the view. +#[test] +fn second_multiple_candidates_per_relay_parent() { + let test_state = TestState::default(); + test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move { + // Candidate `a` is seconded in a parent of the activated `leaf`. + const LEAF_BLOCK_NUMBER: BlockNumber = 100; + const LEAF_DEPTH: BlockNumber = 3; + let para_id = test_state.chain_ids[0]; + + let leaf_hash = Hash::from_low_u64_be(130); + let leaf_parent = get_parent_hash(leaf_hash); + let leaf_grandparent = get_parent_hash(leaf_parent); + let activated = ActivatedLeaf { + hash: leaf_hash, + number: LEAF_BLOCK_NUMBER, + status: LeafStatus::Fresh, + span: Arc::new(jaeger::Span::Disabled), + }; + let min_relay_parents = vec![(para_id, LEAF_BLOCK_NUMBER - LEAF_DEPTH)]; + let test_leaf_a = TestLeaf { activated, min_relay_parents }; + + activate_leaf(&mut virtual_overseer, test_leaf_a, &test_state, 0).await; + + let pov = PoV { block_data: BlockData(vec![42, 43, 44]) }; + let pvd = dummy_pvd(); + let validation_code = ValidationCode(vec![1, 2, 3]); + + let expected_head_data = test_state.head_data.get(¶_id).unwrap(); + + let pov_hash = pov.hash(); + let candidate_a = TestCandidateBuilder { + para_id, + relay_parent: leaf_parent, + pov_hash, + head_data: expected_head_data.clone(), + erasure_root: make_erasure_root(&test_state, pov.clone()), + persisted_validation_data_hash: pvd.hash(), + validation_code: validation_code.0.clone(), + ..Default::default() + }; + let mut candidate_b = candidate_a.clone(); + candidate_b.relay_parent = leaf_grandparent; + + // With depths. + let candidate_a = (candidate_a.build(), 1); + let candidate_b = (candidate_b.build(), 2); + + for candidate in &[candidate_a, candidate_b] { + let (candidate, depth) = candidate; + let second = CandidateBackingMessage::Second( + leaf_hash, + candidate.to_plain(), + pvd.clone(), + pov.clone(), + ); + + virtual_overseer.send(FromOverseer::Communication { msg: second }).await; + + assert_validate_seconded_candidate( + &mut virtual_overseer, + candidate.descriptor().relay_parent, + &candidate, + &pov, + &pvd, + &validation_code, + expected_head_data, + ) + .await; + + // `seconding_sanity_check` + let expected_request_a = vec![( + HypotheticalDepthRequest { + candidate_hash: candidate.hash(), + candidate_para: para_id, + parent_head_data_hash: pvd.parent_head.hash(), + candidate_relay_parent: candidate.descriptor().relay_parent, + fragment_tree_relay_parent: leaf_hash, + }, + vec![*depth], + )]; + assert_hypothetical_depth_requests(&mut virtual_overseer, expected_request_a.clone()) + .await; + + // Prospective parachains are notified. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::CandidateSeconded( + candidate_para, + candidate_receipt, + _pvd, + tx, + ), + ) if &candidate_receipt == candidate && candidate_para == para_id && pvd == _pvd => { + // Any non-empty response will do. + tx.send(vec![(leaf_hash, vec![0, 2, 3])]).unwrap(); + } + ); + + test_dispute_coordinator_notifications( + &mut virtual_overseer, + candidate.hash(), + test_state.session(), + vec![ValidatorIndex(0)], + ) + .await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::Share( + parent_hash, + _signed_statement, + ) + ) if parent_hash == candidate.descriptor().relay_parent => {} + ); + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::CollatorProtocol(CollatorProtocolMessage::Seconded(hash, statement)) => { + assert_eq!(candidate.descriptor().relay_parent, hash); + assert_matches!(statement.payload(), Statement::Seconded(_)); + } + ); + } + + virtual_overseer + }); +}