Files
pezkuwi-sdk/pezkuwi/node/subsystem-bench/src/lib/disputes/test_state.rs
T

223 lines
6.6 KiB
Rust

// Copyright (C) Parity Technologies (UK) Ltd.
// 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 <http://www.gnu.org/licenses/>.
use crate::{
configuration::{TestAuthorities, TestConfiguration},
disputes::DisputesOptions,
network::{HandleNetworkMessage, NetworkMessage},
};
use codec::Encode;
use pezkuwi_node_network_protocol::request_response::{
v1::{DisputeRequest, DisputeResponse},
ProtocolName, Requests,
};
use pezkuwi_node_subsystem_test_helpers::mock::new_block_import_info;
use pezkuwi_overseer::BlockInfo;
use pezkuwi_pez_node_primitives::{
InvalidDisputeVote, SignedDisputeStatement, UncheckedDisputeMessage, ValidDisputeVote,
};
use pezkuwi_primitives::{
AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash,
CandidateReceiptV2, CoreIndex, GroupIndex, Hash, HeadData, Header, InvalidDisputeStatementKind,
SessionIndex, ValidDisputeStatementKind, ValidatorId, ValidatorIndex,
};
use pezkuwi_primitives_test_helpers::{dummy_candidate_receipt_v2_bad_sig, dummy_hash};
use pezsp_keystore::KeystorePtr;
use std::{
collections::{HashMap, HashSet},
sync::{Arc, Mutex},
};
#[derive(Clone)]
pub struct TestState {
// Full test config
pub config: TestConfiguration,
// Authority keys for the network emulation.
pub test_authorities: TestAuthorities,
// Relay chain block infos
pub block_infos: Vec<BlockInfo>,
// Generated candidate receipts
pub candidate_receipts: HashMap<Hash, Vec<CandidateReceiptV2>>,
// Generated candidate events
pub candidate_events: HashMap<Hash, Vec<CandidateEvent>>,
// Generated dispute requests
pub dispute_requests: HashMap<CandidateHash, DisputeRequest>,
// Relay chain block headers
pub block_headers: HashMap<Hash, Header>,
// Map from candidate hash to authorities that have received a dispute request
pub requests_tracker: Arc<Mutex<HashMap<CandidateHash, HashSet<AuthorityDiscoveryId>>>>,
}
impl TestState {
pub fn new(config: &TestConfiguration, options: &DisputesOptions) -> Self {
let config = config.clone();
let test_authorities = config.generate_authorities();
let block_infos: Vec<BlockInfo> =
(1..=config.num_blocks).map(generate_block_info).collect();
let candidate_receipts: HashMap<Hash, Vec<CandidateReceiptV2>> = block_infos
.iter()
.map(|block_info| {
(
block_info.hash,
(0..options.n_disputes)
.map(|_| make_candidate_receipt(block_info.hash))
.collect(),
)
})
.collect();
let candidate_events = candidate_receipts
.iter()
.map(|(&hash, receipts)| {
(
hash,
receipts
.iter()
.map(|receipt| make_candidate_backed_event(receipt.clone()))
.collect::<Vec<_>>(),
)
})
.collect();
let dispute_requests = candidate_receipts
.iter()
.flat_map(|(_, receipts)| {
receipts.iter().map(|receipt| {
let valid = issue_explicit_statement(
test_authorities.keyring.local_keystore(),
test_authorities.validator_public[1].clone(),
receipt.hash(),
1,
true,
);
let invalid = issue_explicit_statement(
test_authorities.keyring.local_keystore(),
test_authorities.validator_public[3].clone(),
receipt.hash(),
1,
false,
);
(
receipt.hash(),
DisputeRequest(UncheckedDisputeMessage {
candidate_receipt: receipt.clone(),
session_index: 1,
valid_vote: ValidDisputeVote {
validator_index: ValidatorIndex(1),
signature: valid.validator_signature().clone(),
kind: ValidDisputeStatementKind::Explicit,
},
invalid_vote: InvalidDisputeVote {
validator_index: ValidatorIndex(3),
signature: invalid.validator_signature().clone(),
kind: InvalidDisputeStatementKind::Explicit,
},
}),
)
})
})
.collect();
let block_headers = block_infos.iter().map(generate_block_header).collect();
let requests_tracker = Arc::new(Mutex::new(HashMap::new()));
Self {
config,
test_authorities,
block_infos,
candidate_receipts,
candidate_events,
dispute_requests,
block_headers,
requests_tracker,
}
}
}
fn make_candidate_receipt(relay_parent: Hash) -> CandidateReceiptV2 {
let mut candidate_receipt = dummy_candidate_receipt_v2_bad_sig(relay_parent, dummy_hash());
candidate_receipt.commitments_hash = CandidateCommitments::default().hash();
candidate_receipt
}
fn make_candidate_backed_event(receipt: CandidateReceiptV2) -> CandidateEvent {
CandidateEvent::CandidateBacked(
receipt,
HeadData::default(),
CoreIndex::default(),
GroupIndex::default(),
)
}
fn generate_block_info(block_num: usize) -> BlockInfo {
new_block_import_info(Hash::repeat_byte(block_num as u8), block_num as BlockNumber)
}
fn generate_block_header(info: &BlockInfo) -> (Hash, Header) {
(
info.hash,
Header {
digest: Default::default(),
number: info.number,
parent_hash: info.parent_hash,
extrinsics_root: Default::default(),
state_root: Default::default(),
},
)
}
fn issue_explicit_statement(
keystore: KeystorePtr,
public: ValidatorId,
candidate_hash: CandidateHash,
session: SessionIndex,
valid: bool,
) -> SignedDisputeStatement {
SignedDisputeStatement::sign_explicit(&keystore, valid, candidate_hash, session, public)
.unwrap()
.unwrap()
}
#[async_trait::async_trait]
impl HandleNetworkMessage for TestState {
async fn handle(
&self,
message: NetworkMessage,
_node_sender: &mut futures::channel::mpsc::UnboundedSender<NetworkMessage>,
) -> Option<NetworkMessage> {
match message {
NetworkMessage::RequestFromNode(authority_id, requests) => {
let Requests::DisputeSendingV1(req) = *requests else {
todo!("Wrong requests type in message: {:?}", requests);
};
let mut tracker = self.requests_tracker.lock().unwrap();
tracker
.entry(req.payload.0.candidate_receipt.hash())
.or_default()
.insert(authority_id);
drop(tracker);
let _ = req
.pending_response
.send(Ok(((DisputeResponse::Confirmed).encode(), ProtocolName::from(""))));
None
},
_ => {
todo!("Wrong message type: {:?}", message);
},
}
}
}