// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
// This file is part of Pezkuwi.
// Pezkuwi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Pezkuwi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Pezkuwi. If not, see .
//! The tests for Approval Voting Parallel Subsystem.
use std::{
collections::{HashMap, HashSet},
future::Future,
sync::Arc,
time::Duration,
};
use crate::{
build_worker_handles, metrics::MetricsWatcher, prio_right, run_main_loop, start_workers,
validator_index_for_msg, ApprovalVotingParallelSubsystem, Metrics, WorkProvider,
};
use assert_matches::assert_matches;
use futures::{channel::oneshot, future, stream::PollNext, StreamExt};
use itertools::Itertools;
use pezkuwi_node_core_approval_voting::{ApprovalVotingWorkProvider, Config};
use pezkuwi_node_network_protocol::{peer_set::ValidationVersion, ObservedRole, PeerId, View};
use pezkuwi_node_subsystem::{
messages::{ApprovalDistributionMessage, ApprovalVotingMessage, ApprovalVotingParallelMessage},
FromOrchestra,
};
use pezkuwi_node_subsystem_test_helpers::{mock::new_leaf, TestSubsystemContext};
use pezkuwi_overseer::{ActiveLeavesUpdate, OverseerSignal, SpawnGlue, TimeoutExt};
use pezkuwi_pez_node_primitives::approval::{
time::SystemClock,
v1::RELAY_VRF_MODULO_CONTEXT,
v2::{
AssignmentCertKindV2, AssignmentCertV2, CoreBitfield, IndirectAssignmentCertV2,
IndirectSignedApprovalVoteV2,
},
};
use pezkuwi_primitives::{CandidateHash, CoreIndex, Hash, ValidatorIndex};
use pezsc_keystore::{Keystore, LocalKeystore};
use pezsp_consensus::SyncOracle;
use pezsp_consensus_babe::{VrfPreOutput, VrfProof, VrfSignature};
use pezsp_core::{testing::TaskExecutor, H256};
use pezsp_keyring::Sr25519Keyring;
type VirtualOverseer =
pezkuwi_node_subsystem_test_helpers::TestSubsystemContextHandle;
const SLOT_DURATION_MILLIS: u64 = 6000;
pub mod test_constants {
pub(crate) const DATA_COL: u32 = 0;
pub(crate) const NUM_COLUMNS: u32 = 1;
}
fn fake_assignment_cert_v2(
block_hash: Hash,
validator: ValidatorIndex,
core_bitfield: CoreBitfield,
) -> IndirectAssignmentCertV2 {
let ctx = schnorrkel::signing_context(RELAY_VRF_MODULO_CONTEXT);
let msg = b"WhenTeyrchains?";
let mut prng = rand_core::OsRng;
let keypair = schnorrkel::Keypair::generate_with(&mut prng);
let (inout, proof, _) = keypair.vrf_sign(ctx.bytes(msg));
let preout = inout.to_preout();
IndirectAssignmentCertV2 {
block_hash,
validator,
cert: AssignmentCertV2 {
kind: AssignmentCertKindV2::RelayVRFModuloCompact { core_bitfield },
vrf: VrfSignature { pre_output: VrfPreOutput(preout), proof: VrfProof(proof) },
},
}
}
/// Creates a meaningless signature
pub fn dummy_signature() -> pezkuwi_primitives::ValidatorSignature {
pezsp_core::crypto::UncheckedFrom::unchecked_from([1u8; 64])
}
fn build_subsystem(
sync_oracle: Box,
) -> (
ApprovalVotingParallelSubsystem,
TestSubsystemContext>,
VirtualOverseer,
) {
pezsp_tracing::init_for_tests();
let pool = pezsp_core::testing::TaskExecutor::new();
let (context, virtual_overseer) = pezkuwi_node_subsystem_test_helpers::make_subsystem_context::<
ApprovalVotingParallelMessage,
_,
>(pool.clone());
let keystore = LocalKeystore::in_memory();
let _ = keystore.sr25519_generate_new(
pezkuwi_primitives::TEYRCHAIN_KEY_TYPE_ID,
Some(&Sr25519Keyring::Alice.to_seed()),
);
let clock = Arc::new(SystemClock {});
let db = kvdb_memorydb::create(test_constants::NUM_COLUMNS);
let db = pezkuwi_node_subsystem_util::database::kvdb_impl::DbAdapter::new(db, &[]);
(
ApprovalVotingParallelSubsystem::with_config_and_clock(
Config {
col_approval_data: test_constants::DATA_COL,
slot_duration_millis: SLOT_DURATION_MILLIS,
},
Arc::new(db),
Arc::new(keystore),
sync_oracle,
Metrics::default(),
clock.clone(),
SpawnGlue(pool),
None,
),
context,
virtual_overseer,
)
}
#[derive(Clone)]
struct TestSyncOracle {}
impl SyncOracle for TestSyncOracle {
fn is_major_syncing(&self) -> bool {
false
}
fn is_offline(&self) -> bool {
unimplemented!("not used in network bridge")
}
}
fn test_harness(
num_approval_distro_workers: usize,
prio_right: Clos,
subsystem_gracefully_exits: bool,
test_fn: impl FnOnce(
VirtualOverseer,
WorkProvider,
Vec>,
) -> T,
) where
T: Future