@@ -1275,6 +1275,242 @@ fn disabled_validators_added_to_unwanted_mask() {
12751275 } ) ;
12761276}
12771277
1278+ #[ test]
1279+ fn no_response_for_grid_request_not_meeting_quorum ( ) {
1280+ let validator_count = 6 ;
1281+ let group_size = 3 ;
1282+ let config = TestConfig {
1283+ validator_count,
1284+ group_size,
1285+ local_validator : true ,
1286+ async_backing_params : None ,
1287+ } ;
1288+
1289+ let relay_parent = Hash :: repeat_byte ( 1 ) ;
1290+ let peer_a = PeerId :: random ( ) ;
1291+ let peer_b = PeerId :: random ( ) ;
1292+ let peer_c = PeerId :: random ( ) ;
1293+
1294+ test_harness ( config, |mut state, mut overseer| async move {
1295+ let local_validator = state. local . clone ( ) . unwrap ( ) ;
1296+ let local_para = ParaId :: from ( local_validator. group_index . 0 ) ;
1297+
1298+ let test_leaf = state. make_dummy_leaf_with_min_backing_votes ( relay_parent, 2 ) ;
1299+
1300+ let ( candidate, pvd) = make_candidate (
1301+ relay_parent,
1302+ 1 ,
1303+ local_para,
1304+ test_leaf. para_data ( local_para) . head_data . clone ( ) ,
1305+ vec ! [ 4 , 5 , 6 ] . into ( ) ,
1306+ Hash :: repeat_byte ( 42 ) . into ( ) ,
1307+ ) ;
1308+ let candidate_hash = candidate. hash ( ) ;
1309+
1310+ let other_group_validators = state. group_validators ( local_validator. group_index , true ) ;
1311+ let target_group_validators =
1312+ state. group_validators ( ( local_validator. group_index . 0 + 1 ) . into ( ) , true ) ;
1313+ let v_a = other_group_validators[ 0 ] ;
1314+ let v_b = other_group_validators[ 1 ] ;
1315+ let v_c = target_group_validators[ 0 ] ;
1316+
1317+ // peer A is in group, has relay parent in view.
1318+ // peer B is in group, has no relay parent in view.
1319+ // peer C is not in group, has relay parent in view.
1320+ {
1321+ connect_peer (
1322+ & mut overseer,
1323+ peer_a. clone ( ) ,
1324+ Some ( vec ! [ state. discovery_id( v_a) ] . into_iter ( ) . collect ( ) ) ,
1325+ )
1326+ . await ;
1327+
1328+ connect_peer (
1329+ & mut overseer,
1330+ peer_b. clone ( ) ,
1331+ Some ( vec ! [ state. discovery_id( v_b) ] . into_iter ( ) . collect ( ) ) ,
1332+ )
1333+ . await ;
1334+
1335+ connect_peer (
1336+ & mut overseer,
1337+ peer_c. clone ( ) ,
1338+ Some ( vec ! [ state. discovery_id( v_c) ] . into_iter ( ) . collect ( ) ) ,
1339+ )
1340+ . await ;
1341+
1342+ send_peer_view_change ( & mut overseer, peer_a. clone ( ) , view ! [ relay_parent] ) . await ;
1343+ send_peer_view_change ( & mut overseer, peer_c. clone ( ) , view ! [ relay_parent] ) . await ;
1344+ }
1345+
1346+ activate_leaf ( & mut overseer, & test_leaf, & state, true ) . await ;
1347+
1348+ answer_expected_hypothetical_depth_request (
1349+ & mut overseer,
1350+ vec ! [ ] ,
1351+ Some ( relay_parent) ,
1352+ false ,
1353+ )
1354+ . await ;
1355+
1356+ // Send gossip topology.
1357+ send_new_topology ( & mut overseer, state. make_dummy_topology ( ) ) . await ;
1358+
1359+ // Confirm the candidate locally so that we don't send out requests.
1360+ {
1361+ let statement = state
1362+ . sign_full_statement (
1363+ local_validator. validator_index ,
1364+ Statement :: Seconded ( candidate. clone ( ) ) ,
1365+ & SigningContext { parent_hash : relay_parent, session_index : 1 } ,
1366+ pvd. clone ( ) ,
1367+ )
1368+ . clone ( ) ;
1369+
1370+ overseer
1371+ . send ( FromOrchestra :: Communication {
1372+ msg : StatementDistributionMessage :: Share ( relay_parent, statement) ,
1373+ } )
1374+ . await ;
1375+
1376+ assert_matches ! (
1377+ overseer. recv( ) . await ,
1378+ AllMessages :: NetworkBridgeTx ( NetworkBridgeTxMessage :: SendValidationMessage ( peers, _) ) if peers == vec![ peer_a]
1379+ ) ;
1380+
1381+ answer_expected_hypothetical_depth_request ( & mut overseer, vec ! [ ] , None , false ) . await ;
1382+ }
1383+
1384+ // Send enough statements to make candidate backable, make sure announcements are sent.
1385+
1386+ // Send statement from peer A.
1387+ {
1388+ let statement = state
1389+ . sign_statement (
1390+ v_a,
1391+ CompactStatement :: Seconded ( candidate_hash) ,
1392+ & SigningContext { parent_hash : relay_parent, session_index : 1 } ,
1393+ )
1394+ . as_unchecked ( )
1395+ . clone ( ) ;
1396+
1397+ send_peer_message (
1398+ & mut overseer,
1399+ peer_a. clone ( ) ,
1400+ protocol_v2:: StatementDistributionMessage :: Statement ( relay_parent, statement) ,
1401+ )
1402+ . await ;
1403+
1404+ assert_matches ! (
1405+ overseer. recv( ) . await ,
1406+ AllMessages :: NetworkBridgeTx ( NetworkBridgeTxMessage :: ReportPeer ( ReportPeerMessage :: Single ( p, r) ) )
1407+ if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST . into( ) => { }
1408+ ) ;
1409+ }
1410+
1411+ // Send statement from peer B.
1412+ let statement_b = state
1413+ . sign_statement (
1414+ v_b,
1415+ CompactStatement :: Seconded ( candidate_hash) ,
1416+ & SigningContext { parent_hash : relay_parent, session_index : 1 } ,
1417+ )
1418+ . as_unchecked ( )
1419+ . clone ( ) ;
1420+ {
1421+ send_peer_message (
1422+ & mut overseer,
1423+ peer_b. clone ( ) ,
1424+ protocol_v2:: StatementDistributionMessage :: Statement (
1425+ relay_parent,
1426+ statement_b. clone ( ) ,
1427+ ) ,
1428+ )
1429+ . await ;
1430+
1431+ assert_matches ! (
1432+ overseer. recv( ) . await ,
1433+ AllMessages :: NetworkBridgeTx ( NetworkBridgeTxMessage :: ReportPeer ( ReportPeerMessage :: Single ( p, r) ) )
1434+ if p == peer_b && r == BENEFIT_VALID_STATEMENT_FIRST . into( ) => { }
1435+ ) ;
1436+
1437+ assert_matches ! (
1438+ overseer. recv( ) . await ,
1439+ AllMessages :: NetworkBridgeTx ( NetworkBridgeTxMessage :: SendValidationMessage ( peers, _) ) if peers == vec![ peer_a]
1440+ ) ;
1441+ }
1442+
1443+ // Send Backed notification.
1444+ {
1445+ overseer
1446+ . send ( FromOrchestra :: Communication {
1447+ msg : StatementDistributionMessage :: Backed ( candidate_hash) ,
1448+ } )
1449+ . await ;
1450+
1451+ assert_matches ! (
1452+ overseer. recv( ) . await ,
1453+ AllMessages :: NetworkBridgeTx (
1454+ NetworkBridgeTxMessage :: SendValidationMessage (
1455+ peers,
1456+ Versioned :: V2 (
1457+ protocol_v2:: ValidationProtocol :: StatementDistribution (
1458+ protocol_v2:: StatementDistributionMessage :: BackedCandidateManifest ( manifest) ,
1459+ ) ,
1460+ ) ,
1461+ )
1462+ ) => {
1463+ assert_eq!( peers, vec![ peer_c] ) ;
1464+ assert_eq!( manifest, BackedCandidateManifest {
1465+ relay_parent,
1466+ candidate_hash,
1467+ group_index: local_validator. group_index,
1468+ para_id: local_para,
1469+ parent_head_data_hash: pvd. parent_head. hash( ) ,
1470+ statement_knowledge: StatementFilter {
1471+ seconded_in_group: bitvec:: bitvec![ u8 , Lsb0 ; 1 , 1 , 1 ] ,
1472+ validated_in_group: bitvec:: bitvec![ u8 , Lsb0 ; 0 , 0 , 0 ] ,
1473+ } ,
1474+ } ) ;
1475+ }
1476+ ) ;
1477+
1478+ answer_expected_hypothetical_depth_request ( & mut overseer, vec ! [ ] , None , false ) . await ;
1479+ }
1480+
1481+ let mask = StatementFilter {
1482+ seconded_in_group : bitvec:: bitvec![ u8 , Lsb0 ; 0 , 0 , 1 ] ,
1483+ validated_in_group : bitvec:: bitvec![ u8 , Lsb0 ; 0 , 0 , 0 ] ,
1484+ } ;
1485+
1486+ let relay_2 = Hash :: repeat_byte ( 2 ) ;
1487+ let disabled_validators = vec ! [ v_a] ;
1488+ let leaf_2 = state. make_dummy_leaf_with_disabled_validators ( relay_2, disabled_validators) ;
1489+ activate_leaf ( & mut overseer, & leaf_2, & state, false ) . await ;
1490+ answer_expected_hypothetical_depth_request ( & mut overseer, vec ! [ ] , Some ( relay_2) , false )
1491+ . await ;
1492+
1493+ // Incoming request to local node. Local node should not send the response as v_a is
1494+ // disabled and hence the quorum is not reached.
1495+ {
1496+ let response = state
1497+ . send_request (
1498+ peer_c,
1499+ request_v2:: AttestedCandidateRequest { candidate_hash : candidate. hash ( ) , mask } ,
1500+ )
1501+ . await
1502+ . await ;
1503+
1504+ assert ! (
1505+ response. is_none( ) ,
1506+ "We should not send a response as the quorum is not reached yet"
1507+ ) ;
1508+ }
1509+
1510+ overseer
1511+ } ) ;
1512+ }
1513+
12781514#[ test]
12791515fn disabling_works_from_the_latest_state_not_relay_parent ( ) {
12801516 let group_size = 3 ;
@@ -1850,7 +2086,7 @@ fn local_node_respects_statement_mask() {
18502086 let local_validator = state. local . clone ( ) . unwrap ( ) ;
18512087 let local_para = ParaId :: from ( local_validator. group_index . 0 ) ;
18522088
1853- let test_leaf = state. make_dummy_leaf_with_min_backing_votes ( relay_parent, 1 ) ;
2089+ let test_leaf = state. make_dummy_leaf_with_min_backing_votes ( relay_parent, 2 ) ;
18542090
18552091 let ( candidate, pvd) = make_candidate (
18562092 relay_parent,
@@ -1948,20 +2184,22 @@ fn local_node_respects_statement_mask() {
19482184 // Send enough statements to make candidate backable, make sure announcements are sent.
19492185
19502186 // Send statement from peer A.
2187+ let statement_a = state
2188+ . sign_statement (
2189+ v_a,
2190+ CompactStatement :: Seconded ( candidate_hash) ,
2191+ & SigningContext { parent_hash : relay_parent, session_index : 1 } ,
2192+ )
2193+ . as_unchecked ( )
2194+ . clone ( ) ;
19512195 {
1952- let statement = state
1953- . sign_statement (
1954- v_a,
1955- CompactStatement :: Seconded ( candidate_hash) ,
1956- & SigningContext { parent_hash : relay_parent, session_index : 1 } ,
1957- )
1958- . as_unchecked ( )
1959- . clone ( ) ;
1960-
19612196 send_peer_message (
19622197 & mut overseer,
19632198 peer_a. clone ( ) ,
1964- protocol_v2:: StatementDistributionMessage :: Statement ( relay_parent, statement) ,
2199+ protocol_v2:: StatementDistributionMessage :: Statement (
2200+ relay_parent,
2201+ statement_a. clone ( ) ,
2202+ ) ,
19652203 )
19662204 . await ;
19672205
@@ -2044,7 +2282,7 @@ fn local_node_respects_statement_mask() {
20442282
20452283 // `1` indicates statements NOT to request.
20462284 let mask = StatementFilter {
2047- seconded_in_group : bitvec:: bitvec![ u8 , Lsb0 ; 1 , 0 , 1 ] ,
2285+ seconded_in_group : bitvec:: bitvec![ u8 , Lsb0 ; 0 , 0 , 1 ] ,
20482286 validated_in_group : bitvec:: bitvec![ u8 , Lsb0 ; 0 , 0 , 0 ] ,
20492287 } ;
20502288
@@ -2059,7 +2297,7 @@ fn local_node_respects_statement_mask() {
20592297 . await
20602298 . unwrap ( ) ;
20612299
2062- let expected_statements = vec ! [ statement_b] ;
2300+ let expected_statements = vec ! [ statement_a , statement_b] ;
20632301 assert_matches ! ( response, full_response => {
20642302 // Response is the same for v2.
20652303 let request_v2:: AttestedCandidateResponse { candidate_receipt, persisted_validation_data, statements } =
0 commit comments