From 640264f38b1fdecf9c1f5446ac8c966ee0ec657b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <bkchr@users.noreply.github.com> Date: Thu, 5 Nov 2020 16:28:45 +0100 Subject: [PATCH] Make `CandidateHash` a real type (#1916) * Make `CandidateHash` a real type This pr adds a new type `CandidateHash` that is used instead of the opaque `Hash` type. This helps to ensure on the type system level that we are passing the correct types. This pr also fixes wrong usage of `relay_parent` as `candidate_hash` when communicating with the av storage. * Update core-primitives/src/lib.rs Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> * Wrap the lines Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> --- polkadot/core-primitives/src/lib.rs | 8 +++ polkadot/node/core/av-store/src/lib.rs | 35 ++++++---- polkadot/node/core/av-store/src/tests.rs | 18 ++--- polkadot/node/core/backing/src/lib.rs | 37 +++++----- .../node/core/bitfield-signing/src/lib.rs | 2 +- .../availability-distribution/src/lib.rs | 67 ++++++++++--------- .../availability-distribution/src/tests.rs | 4 +- polkadot/node/network/protocol/src/lib.rs | 4 +- .../network/statement-distribution/src/lib.rs | 62 ++++++++--------- polkadot/node/overseer/src/lib.rs | 4 +- polkadot/node/primitives/src/lib.rs | 6 +- polkadot/node/subsystem/src/messages.rs | 14 ++-- polkadot/primitives/src/v0.rs | 10 +-- polkadot/primitives/src/v1.rs | 10 +-- .../implementers-guide/src/types/network.md | 2 +- .../src/types/overseer-protocol.md | 10 +-- polkadot/statement-table/src/lib.rs | 52 ++------------ 17 files changed, 162 insertions(+), 183 deletions(-) diff --git a/polkadot/core-primitives/src/lib.rs b/polkadot/core-primitives/src/lib.rs index d3f567f66a0..0e080fff6f7 100644 --- a/polkadot/core-primitives/src/lib.rs +++ b/polkadot/core-primitives/src/lib.rs @@ -50,6 +50,14 @@ pub type ChainId = u32; /// A hash of some data used by the relay chain. pub type Hash = sp_core::H256; +/// Unit type wrapper around [`Hash`] that represents a candidate hash. +/// +/// This type is produced by [`CandidateReceipt::hash`]. +/// +/// This type makes it easy to enforce that a hash is a candidate hash on the type level. +#[derive(Clone, Copy, codec::Encode, codec::Decode, Hash, Eq, PartialEq, Debug, Default)] +pub struct CandidateHash(pub Hash); + /// Index of a transaction in the relay chain. 32-bit should be plenty. pub type Nonce = u32; diff --git a/polkadot/node/core/av-store/src/lib.rs b/polkadot/node/core/av-store/src/lib.rs index 0f248ba347e..57bd6d804c6 100644 --- a/polkadot/node/core/av-store/src/lib.rs +++ b/polkadot/node/core/av-store/src/lib.rs @@ -33,7 +33,7 @@ use kvdb_rocksdb::{Database, DatabaseConfig}; use kvdb::{KeyValueDB, DBTransaction}; use polkadot_primitives::v1::{ - Hash, AvailableData, BlockNumber, CandidateEvent, ErasureChunk, ValidatorIndex, + Hash, AvailableData, BlockNumber, CandidateEvent, ErasureChunk, ValidatorIndex, CandidateHash, }; use polkadot_subsystem::{ FromOverseer, OverseerSignal, SubsystemError, Subsystem, SubsystemContext, SpawnedSubsystem, @@ -242,7 +242,7 @@ enum CandidateState { #[derive(Debug, Decode, Encode, Eq)] struct PoVPruningRecord { - candidate_hash: Hash, + candidate_hash: CandidateHash, block_number: BlockNumber, candidate_state: CandidateState, prune_at: PruningDelay, @@ -272,7 +272,7 @@ impl PartialOrd for PoVPruningRecord { #[derive(Debug, Decode, Encode, Eq)] struct ChunkPruningRecord { - candidate_hash: Hash, + candidate_hash: CandidateHash, block_number: BlockNumber, candidate_state: CandidateState, chunk_index: u32, @@ -387,11 +387,11 @@ impl AvailabilityStoreSubsystem { } } -fn available_data_key(candidate_hash: &Hash) -> Vec<u8> { +fn available_data_key(candidate_hash: &CandidateHash) -> Vec<u8> { (candidate_hash, 0i8).encode() } -fn erasure_chunk_key(candidate_hash: &Hash, index: u32) -> Vec<u8> { +fn erasure_chunk_key(candidate_hash: &CandidateHash, index: u32) -> Vec<u8> { (candidate_hash, index, 0i8).encode() } @@ -564,7 +564,7 @@ where log::trace!( target: LOG_TARGET, "Updating pruning record for finalized block {}", - record.candidate_hash, + record.block_number, ); record.prune_at = PruningDelay::into_the_future( @@ -583,7 +583,7 @@ where log::trace!( target: LOG_TARGET, "Updating chunk pruning record for finalized block {}", - record.candidate_hash, + record.block_number, ); record.prune_at = PruningDelay::into_the_future( @@ -620,7 +620,7 @@ where for event in events.into_iter() { if let CandidateEvent::CandidateIncluded(receipt, _) = event { - log::trace!(target: LOG_TARGET, "Candidate {} was included", receipt.hash()); + log::trace!(target: LOG_TARGET, "Candidate {:?} was included", receipt.hash()); included.insert(receipt.hash()); } } @@ -729,7 +729,10 @@ where Ok(()) } -fn available_data(db: &Arc<dyn KeyValueDB>, candidate_hash: &Hash) -> Option<StoredAvailableData> { +fn available_data( + db: &Arc<dyn KeyValueDB>, + candidate_hash: &CandidateHash, +) -> Option<StoredAvailableData> { query_inner(db, columns::DATA, &available_data_key(candidate_hash)) } @@ -835,7 +838,7 @@ where fn store_available_data( subsystem: &mut AvailabilityStoreSubsystem, - candidate_hash: &Hash, + candidate_hash: &CandidateHash, id: Option<ValidatorIndex>, n_validators: u32, available_data: AvailableData, @@ -872,7 +875,7 @@ fn store_available_data( } let pruning_record = PoVPruningRecord { - candidate_hash: candidate_hash.clone(), + candidate_hash: *candidate_hash, block_number, candidate_state: CandidateState::Stored, prune_at, @@ -901,7 +904,7 @@ fn store_available_data( fn store_chunk( subsystem: &mut AvailabilityStoreSubsystem, - candidate_hash: &Hash, + candidate_hash: &CandidateHash, _n_validators: u32, chunk: ErasureChunk, block_number: BlockNumber, @@ -952,7 +955,7 @@ fn store_chunk( fn get_chunk( subsystem: &mut AvailabilityStoreSubsystem, - candidate_hash: &Hash, + candidate_hash: &CandidateHash, index: u32, ) -> Result<Option<ErasureChunk>, Error> { if let Some(chunk) = query_inner( @@ -981,7 +984,11 @@ fn get_chunk( Ok(None) } -fn query_inner<D: Decode>(db: &Arc<dyn KeyValueDB>, column: u32, key: &[u8]) -> Option<D> { +fn query_inner<D: Decode>( + db: &Arc<dyn KeyValueDB>, + column: u32, + key: &[u8], +) -> Option<D> { match db.get(column, key) { Ok(Some(raw)) => { let res = D::decode(&mut &raw[..]).expect("all stored data serialized correctly; qed"); diff --git a/polkadot/node/core/av-store/src/tests.rs b/polkadot/node/core/av-store/src/tests.rs index c2d6c9550ac..acbab53f12c 100644 --- a/polkadot/node/core/av-store/src/tests.rs +++ b/polkadot/node/core/av-store/src/tests.rs @@ -27,7 +27,7 @@ use smallvec::smallvec; use polkadot_primitives::v1::{ AvailableData, BlockData, CandidateDescriptor, CandidateReceipt, HeadData, - PersistedValidationData, PoV, Id as ParaId, + PersistedValidationData, PoV, Id as ParaId, CandidateHash, }; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_subsystem::{ @@ -199,7 +199,7 @@ fn runtime_api_error_does_not_stop_the_subsystem() { // but that's fine, we're still alive let (tx, rx) = oneshot::channel(); - let candidate_hash = Hash::repeat_byte(33); + let candidate_hash = CandidateHash(Hash::repeat_byte(33)); let validator_index = 5; let query_chunk = AvailabilityStoreMessage::QueryChunk( candidate_hash, @@ -220,7 +220,7 @@ fn store_chunk_works() { test_harness(PruningConfig::default(), store.clone(), |test_harness| async move { let TestHarness { mut virtual_overseer } = test_harness; let relay_parent = Hash::repeat_byte(32); - let candidate_hash = Hash::repeat_byte(33); + let candidate_hash = CandidateHash(Hash::repeat_byte(33)); let validator_index = 5; let chunk = ErasureChunk { @@ -273,7 +273,7 @@ fn store_block_works() { let test_state = TestState::default(); test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move { let TestHarness { mut virtual_overseer } = test_harness; - let candidate_hash = Hash::from([1; 32]); + let candidate_hash = CandidateHash(Hash::from([1; 32])); let validator_index = 5; let n_validators = 10; @@ -327,7 +327,7 @@ fn store_pov_and_query_chunk_works() { test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move { let TestHarness { mut virtual_overseer } = test_harness; - let candidate_hash = Hash::from([1; 32]); + let candidate_hash = CandidateHash(Hash::from([1; 32])); let n_validators = 10; let pov = PoV { @@ -370,7 +370,7 @@ fn stored_but_not_included_chunk_is_pruned() { test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move { let TestHarness { mut virtual_overseer } = test_harness; - let candidate_hash = Hash::repeat_byte(1); + let candidate_hash = CandidateHash(Hash::repeat_byte(1)); let relay_parent = Hash::repeat_byte(2); let validator_index = 5; @@ -425,7 +425,7 @@ fn stored_but_not_included_data_is_pruned() { test_harness(test_state.pruning_config.clone(), store.clone(), |test_harness| async move { let TestHarness { mut virtual_overseer } = test_harness; - let candidate_hash = Hash::repeat_byte(1); + let candidate_hash = CandidateHash(Hash::repeat_byte(1)); let n_validators = 10; let pov = PoV { @@ -852,7 +852,7 @@ fn forkfullness_works() { async fn query_available_data( virtual_overseer: &mut test_helpers::TestSubsystemContextHandle<AvailabilityStoreMessage>, - candidate_hash: Hash, + candidate_hash: CandidateHash, ) -> Option<AvailableData> { let (tx, rx) = oneshot::channel(); @@ -864,7 +864,7 @@ async fn query_available_data( async fn query_chunk( virtual_overseer: &mut test_helpers::TestSubsystemContextHandle<AvailabilityStoreMessage>, - candidate_hash: Hash, + candidate_hash: CandidateHash, index: u32, ) -> Option<ErasureChunk> { let (tx, rx) = oneshot::channel(); diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 175b4732724..0cb1c40cdcb 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -32,7 +32,7 @@ use futures::{ use sp_keystore::SyncCryptoStorePtr; use polkadot_primitives::v1::{ CommittedCandidateReceipt, BackedCandidate, Id as ParaId, ValidatorId, - ValidatorIndex, SigningContext, PoV, + ValidatorIndex, SigningContext, PoV, CandidateHash, CandidateDescriptor, AvailableData, ValidatorSignature, Hash, CandidateReceipt, CandidateCommitments, CoreState, CoreIndex, CollatorId, ValidationOutputs, }; @@ -103,12 +103,12 @@ struct CandidateBackingJob { /// The collator required to author the candidate, if any. required_collator: Option<CollatorId>, /// We issued `Valid` or `Invalid` statements on about these candidates. - issued_statements: HashSet<Hash>, + issued_statements: HashSet<CandidateHash>, /// `Some(h)` if this job has already issues `Seconded` statemt for some candidate with `h` hash. - seconded: Option<Hash>, + seconded: Option<CandidateHash>, /// The candidates that are includable, by hash. Each entry here indicates /// that we've sent the provisioner the backed candidate. - backed: HashSet<Hash>, + backed: HashSet<CandidateHash>, /// We have already reported misbehaviors for these validators. reported_misbehavior_for: HashSet<ValidatorIndex>, keystore: SyncCryptoStorePtr, @@ -131,12 +131,12 @@ struct TableContext { impl TableContextTrait for TableContext { type AuthorityId = ValidatorIndex; - type Digest = Hash; + type Digest = CandidateHash; type GroupId = ParaId; type Signature = ValidatorSignature; type Candidate = CommittedCandidateReceipt; - fn candidate_digest(candidate: &CommittedCandidateReceipt) -> Hash { + fn candidate_digest(candidate: &CommittedCandidateReceipt) -> CandidateHash { candidate.hash() } @@ -341,6 +341,7 @@ impl CandidateBackingJob { // the collator, do not make available and report the collator. let commitments_check = self.make_pov_available( pov, + candidate_hash, validation_data, outputs, |commitments| if commitments.hash() == candidate.commitments_hash { @@ -525,7 +526,7 @@ impl CandidateBackingJob { &mut self, summary: TableSummary, ) -> Result<(), Error> { - let candidate_hash = summary.candidate.clone(); + let candidate_hash = summary.candidate; if self.issued_statements.contains(&candidate_hash) { return Ok(()) @@ -559,6 +560,7 @@ impl CandidateBackingJob { // If validation produces a new set of commitments, we vote the candidate as invalid. let commitments_check = self.make_pov_available( (&*pov).clone(), + candidate_hash, validation_data, outputs, |commitments| if commitments == expected_commitments { @@ -667,12 +669,13 @@ impl CandidateBackingJob { &mut self, id: Option<ValidatorIndex>, n_validators: u32, + candidate_hash: CandidateHash, available_data: AvailableData, ) -> Result<(), Error> { let (tx, rx) = oneshot::channel(); self.tx_from.send(FromJob::AvailabilityStore( AvailabilityStoreMessage::StoreAvailableData( - self.parent, + candidate_hash, id, n_validators, available_data, @@ -694,6 +697,7 @@ impl CandidateBackingJob { async fn make_pov_available<T, E>( &mut self, pov: PoV, + candidate_hash: CandidateHash, validation_data: polkadot_primitives::v1::PersistedValidationData, outputs: ValidationOutputs, with_commitments: impl FnOnce(CandidateCommitments) -> Result<T, E>, @@ -727,6 +731,7 @@ impl CandidateBackingJob { self.store_available_data( self.table_context.validator.as_ref().map(|v| v.index()), self.table_context.validators.len() as u32, + candidate_hash, available_data, ).await?; @@ -1206,8 +1211,8 @@ mod tests { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityStore( - AvailabilityStoreMessage::StoreAvailableData(parent_hash, _, _, _, tx) - ) if parent_hash == test_state.relay_parent => { + AvailabilityStoreMessage::StoreAvailableData(candidate_hash, _, _, _, tx) + ) if candidate_hash == candidate.hash() => { tx.send(Ok(())).unwrap(); } ); @@ -1333,8 +1338,8 @@ mod tests { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityStore( - AvailabilityStoreMessage::StoreAvailableData(parent_hash, _, _, _, tx) - ) if parent_hash == test_state.relay_parent => { + AvailabilityStoreMessage::StoreAvailableData(candidate_hash, _, _, _, tx) + ) if candidate_hash == candidate_a.hash() => { tx.send(Ok(())).unwrap(); } ); @@ -1482,8 +1487,8 @@ mod tests { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityStore( - AvailabilityStoreMessage::StoreAvailableData(parent_hash, _, _, _, tx) - ) if parent_hash == test_state.relay_parent => { + AvailabilityStoreMessage::StoreAvailableData(candidate_hash, _, _, _, tx) + ) if candidate_hash == candidate_a.hash() => { tx.send(Ok(())).unwrap(); } ); @@ -1665,8 +1670,8 @@ mod tests { assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityStore( - AvailabilityStoreMessage::StoreAvailableData(parent_hash, _, _, _, tx) - ) if parent_hash == test_state.relay_parent => { + AvailabilityStoreMessage::StoreAvailableData(candidate_hash, _, _, _, tx) + ) if candidate_hash == candidate_b.hash() => { tx.send(Ok(())).unwrap(); } ); diff --git a/polkadot/node/core/bitfield-signing/src/lib.rs b/polkadot/node/core/bitfield-signing/src/lib.rs index f91bd3ba7b3..8a351805802 100644 --- a/polkadot/node/core/bitfield-signing/src/lib.rs +++ b/polkadot/node/core/bitfield-signing/src/lib.rs @@ -174,7 +174,7 @@ async fn get_core_availability( .await .send( AvailabilityStoreMessage::QueryChunkAvailability( - committed_candidate_receipt.descriptor.pov_hash, + committed_candidate_receipt.hash(), validator_idx, tx, ).into(), diff --git a/polkadot/node/network/availability-distribution/src/lib.rs b/polkadot/node/network/availability-distribution/src/lib.rs index 9badc682f68..3c86911b257 100644 --- a/polkadot/node/network/availability-distribution/src/lib.rs +++ b/polkadot/node/network/availability-distribution/src/lib.rs @@ -38,7 +38,7 @@ use polkadot_node_network_protocol::{ use polkadot_node_subsystem_util::metrics::{self, prometheus}; use polkadot_primitives::v1::{ BlakeTwo256, CommittedCandidateReceipt, CoreState, ErasureChunk, Hash, HashT, Id as ParaId, - SessionIndex, ValidatorId, ValidatorIndex, PARACHAIN_KEY_TYPE_ID, + SessionIndex, ValidatorId, ValidatorIndex, PARACHAIN_KEY_TYPE_ID, CandidateHash, }; use polkadot_subsystem::messages::{ AllMessages, AvailabilityDistributionMessage, AvailabilityStoreMessage, ChainApiMessage, @@ -130,7 +130,7 @@ const BENEFIT_VALID_MESSAGE: Rep = Rep::new(10, "Valid message"); #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, Hash)] pub struct AvailabilityGossipMessage { /// Anchor hash of the candidate the `ErasureChunk` is associated to. - pub candidate_hash: Hash, + pub candidate_hash: CandidateHash, /// The erasure chunk, a encoded information part of `AvailabilityData`. pub erasure_chunk: ErasureChunk, } @@ -149,13 +149,13 @@ struct ProtocolState { /// Caches a mapping of relay parents or ancestor to live candidate receipts. /// Allows fast intersection of live candidates with views and consecutive unioning. /// Maps relay parent / ancestor -> live candidate receipts + its hash. - receipts: HashMap<Hash, HashSet<(Hash, CommittedCandidateReceipt)>>, + receipts: HashMap<Hash, HashSet<(CandidateHash, CommittedCandidateReceipt)>>, /// Allow reverse caching of view checks. /// Maps candidate hash -> relay parent for extracting meta information from `PerRelayParent`. /// Note that the presence of this is not sufficient to determine if deletion is OK, i.e. /// two histories could cover this. - reverse: HashMap<Hash, Hash>, + reverse: HashMap<CandidateHash, Hash>, /// Keeps track of which candidate receipts are required due to ancestors of which relay parents /// of our view. @@ -166,7 +166,7 @@ struct ProtocolState { per_relay_parent: HashMap<Hash, PerRelayParent>, /// Track data that is specific to a candidate. - per_candidate: HashMap<Hash, PerCandidate>, + per_candidate: HashMap<CandidateHash, PerCandidate>, } #[derive(Debug, Clone, Default)] @@ -176,11 +176,11 @@ struct PerCandidate { /// candidate hash + erasure chunk index -> gossip message message_vault: HashMap<u32, AvailabilityGossipMessage>, - /// Track received candidate hashes and chunk indices from peers. - received_messages: HashMap<PeerId, HashSet<(Hash, ValidatorIndex)>>, + /// Track received candidate hashes and validator indices from peers. + received_messages: HashMap<PeerId, HashSet<(CandidateHash, ValidatorIndex)>>, /// Track already sent candidate hashes and the erasure chunk index to the peers. - sent_messages: HashMap<PeerId, HashSet<(Hash, ValidatorIndex)>>, + sent_messages: HashMap<PeerId, HashSet<(CandidateHash, ValidatorIndex)>>, /// The set of validators. validators: Vec<ValidatorId>, @@ -221,7 +221,7 @@ impl ProtocolState { fn cached_live_candidates_unioned<'a>( &'a self, relay_parents: impl IntoIterator<Item = &'a Hash> + 'a, - ) -> HashMap<Hash, CommittedCandidateReceipt> { + ) -> HashMap<CandidateHash, CommittedCandidateReceipt> { let relay_parents_and_ancestors = self.extend_with_ancestors(relay_parents); relay_parents_and_ancestors .into_iter() @@ -229,7 +229,7 @@ impl ProtocolState { .map(|receipt_set| receipt_set.into_iter()) .flatten() .map(|(receipt_hash, receipt)| (receipt_hash.clone(), receipt.clone())) - .collect::<HashMap<Hash, CommittedCandidateReceipt>>() + .collect() } async fn add_relay_parent<Context>( @@ -296,8 +296,9 @@ impl ProtocolState { // remove from the ancestry index self.ancestry.remove(relay_parent); // and also remove the actual receipt - self.receipts.remove(relay_parent); - self.per_candidate.remove(relay_parent); + if let Some(candidates) = self.receipts.remove(relay_parent) { + candidates.into_iter().for_each(|c| { self.per_candidate.remove(&c.0); }); + } } } if let Some(per_relay_parent) = self.per_relay_parent.remove(relay_parent) { @@ -313,8 +314,9 @@ impl ProtocolState { // remove from the ancestry index self.ancestry.remove(&ancestor); // and also remove the actual receipt - self.receipts.remove(&ancestor); - self.per_candidate.remove(&ancestor); + if let Some(candidates) = self.receipts.remove(&ancestor) { + candidates.into_iter().for_each(|c| { self.per_candidate.remove(&c.0); }); + } } } } @@ -645,8 +647,7 @@ where let live_candidates = state.cached_live_candidates_unioned(state.view.0.iter()); // check if the candidate is of interest - let live_candidate = if let Some(live_candidate) = live_candidates.get(&message.candidate_hash) - { + let live_candidate = if let Some(live_candidate) = live_candidates.get(&message.candidate_hash) { live_candidate } else { return modify_reputation(ctx, origin, COST_NOT_A_LIVE_CANDIDATE).await; @@ -862,7 +863,7 @@ async fn query_live_candidates<Context>( ctx: &mut Context, state: &mut ProtocolState, relay_parents: impl IntoIterator<Item = Hash>, -) -> Result<HashMap<Hash, (Hash, CommittedCandidateReceipt)>> +) -> Result<HashMap<Hash, (CandidateHash, CommittedCandidateReceipt)>> where Context: SubsystemContext<Message = AvailabilityDistributionMessage>, { @@ -871,7 +872,7 @@ where let capacity = hint.1.unwrap_or(hint.0) * (1 + AvailabilityDistributionSubsystem::K); let mut live_candidates = - HashMap::<Hash, (Hash, CommittedCandidateReceipt)>::with_capacity(capacity); + HashMap::<Hash, (CandidateHash, CommittedCandidateReceipt)>::with_capacity(capacity); for relay_parent in iter { // register one of relay parents (not the ancestors) @@ -969,7 +970,7 @@ where } /// Query the proof of validity for a particular candidate hash. -async fn query_data_availability<Context>(ctx: &mut Context, candidate_hash: Hash) -> Result<bool> +async fn query_data_availability<Context>(ctx: &mut Context, candidate_hash: CandidateHash) -> Result<bool> where Context: SubsystemContext<Message = AvailabilityDistributionMessage>, { @@ -985,7 +986,7 @@ where async fn query_chunk<Context>( ctx: &mut Context, - candidate_hash: Hash, + candidate_hash: CandidateHash, validator_index: ValidatorIndex, ) -> Result<Option<ErasureChunk>> where @@ -1002,7 +1003,7 @@ where async fn store_chunk<Context>( ctx: &mut Context, - candidate_hash: Hash, + candidate_hash: CandidateHash, relay_parent: Hash, validator_index: ValidatorIndex, erasure_chunk: ErasureChunk, @@ -1012,18 +1013,18 @@ where { let (tx, rx) = oneshot::channel(); ctx.send_message( - AllMessages::AvailabilityStore( - AvailabilityStoreMessage::StoreChunk { - candidate_hash, - relay_parent, - validator_index, - chunk: erasure_chunk, - tx, - } - )).await - .map_err(|e| Error::StoreChunkSendQuery(e))?; - - rx.await.map_err(|e| Error::StoreChunkResponseChannel(e)) + AllMessages::AvailabilityStore( + AvailabilityStoreMessage::StoreChunk { + candidate_hash, + relay_parent, + validator_index, + chunk: erasure_chunk, + tx, + } + )).await + .map_err(|e| Error::StoreChunkSendQuery(e))?; + + rx.await.map_err(|e| Error::StoreChunkResponseChannel(e)) } /// Request the head data for a particular para. diff --git a/polkadot/node/network/availability-distribution/src/tests.rs b/polkadot/node/network/availability-distribution/src/tests.rs index 8012da546b0..e3e60e1f9e5 100644 --- a/polkadot/node/network/availability-distribution/src/tests.rs +++ b/polkadot/node/network/availability-distribution/src/tests.rs @@ -254,7 +254,7 @@ fn make_erasure_root(test: &TestState, pov: PoV) -> Hash { fn make_valid_availability_gossip( test: &TestState, - candidate_hash: Hash, + candidate_hash: CandidateHash, erasure_chunk_index: u32, pov: PoV, ) -> AvailabilityGossipMessage { @@ -320,7 +320,7 @@ fn helper_integrity() { .build(); let message = - make_valid_availability_gossip(&test_state, dbg!(candidate.hash()), 2, pov_block.clone()); + make_valid_availability_gossip(&test_state, candidate.hash(), 2, pov_block.clone()); let root = dbg!(&candidate.commitments.erasure_root); diff --git a/polkadot/node/network/protocol/src/lib.rs b/polkadot/node/network/protocol/src/lib.rs index 31ec729d8b8..cd3aca73be9 100644 --- a/polkadot/node/network/protocol/src/lib.rs +++ b/polkadot/node/network/protocol/src/lib.rs @@ -186,7 +186,7 @@ impl View { pub mod v1 { use polkadot_primitives::v1::{ Hash, CollatorId, Id as ParaId, ErasureChunk, CandidateReceipt, - SignedAvailabilityBitfield, PoV, + SignedAvailabilityBitfield, PoV, CandidateHash, }; use polkadot_node_primitives::SignedFullStatement; use parity_scale_codec::{Encode, Decode}; @@ -198,7 +198,7 @@ pub mod v1 { pub enum AvailabilityDistributionMessage { /// An erasure chunk for a given candidate hash. #[codec(index = "0")] - Chunk(Hash, ErasureChunk), + Chunk(CandidateHash, ErasureChunk), } /// Network messages used by the bitfield distribution subsystem. diff --git a/polkadot/node/network/statement-distribution/src/lib.rs b/polkadot/node/network/statement-distribution/src/lib.rs index 180b66eee1a..bb4c192c4ff 100644 --- a/polkadot/node/network/statement-distribution/src/lib.rs +++ b/polkadot/node/network/statement-distribution/src/lib.rs @@ -35,7 +35,7 @@ use polkadot_node_subsystem_util::{ }; use node_primitives::SignedFullStatement; use polkadot_primitives::v1::{ - Hash, CompactStatement, ValidatorIndex, ValidatorId, SigningContext, ValidatorSignature, + Hash, CompactStatement, ValidatorIndex, ValidatorId, SigningContext, ValidatorSignature, CandidateHash, }; use polkadot_node_network_protocol::{ v1 as protocol_v1, View, PeerId, ReputationChange as Rep, NetworkBridgeEvent, @@ -102,32 +102,32 @@ impl StatementDistribution { /// via other means. #[derive(Default)] struct VcPerPeerTracker { - local_observed: arrayvec::ArrayVec<[Hash; VC_THRESHOLD]>, - remote_observed: arrayvec::ArrayVec<[Hash; VC_THRESHOLD]>, + local_observed: arrayvec::ArrayVec<[CandidateHash; VC_THRESHOLD]>, + remote_observed: arrayvec::ArrayVec<[CandidateHash; VC_THRESHOLD]>, } impl VcPerPeerTracker { - // Note that the remote should now be aware that a validator has seconded a given candidate (by hash) - // based on a message that we have sent it from our local pool. - fn note_local(&mut self, h: Hash) { + /// Note that the remote should now be aware that a validator has seconded a given candidate (by hash) + /// based on a message that we have sent it from our local pool. + fn note_local(&mut self, h: CandidateHash) { if !note_hash(&mut self.local_observed, h) { log::warn!("Statement distribution is erroneously attempting to distribute more \ than {} candidate(s) per validator index. Ignoring", VC_THRESHOLD); } } - // Note that the remote should now be aware that a validator has seconded a given candidate (by hash) - // based on a message that it has sent us. - // - // Returns `true` if the peer was allowed to send us such a message, `false` otherwise. - fn note_remote(&mut self, h: Hash) -> bool { + /// Note that the remote should now be aware that a validator has seconded a given candidate (by hash) + /// based on a message that it has sent us. + /// + /// Returns `true` if the peer was allowed to send us such a message, `false` otherwise. + fn note_remote(&mut self, h: CandidateHash) -> bool { note_hash(&mut self.remote_observed, h) } } fn note_hash( - observed: &mut arrayvec::ArrayVec<[Hash; VC_THRESHOLD]>, - h: Hash, + observed: &mut arrayvec::ArrayVec<[CandidateHash; VC_THRESHOLD]>, + h: CandidateHash, ) -> bool { if observed.contains(&h) { return true; } @@ -139,7 +139,7 @@ fn note_hash( struct PeerRelayParentKnowledge { /// candidates that the peer is aware of. This indicates that we can /// send other statements pertaining to that candidate. - known_candidates: HashSet<Hash>, + known_candidates: HashSet<CandidateHash>, /// fingerprints of all statements a peer should be aware of: those that /// were sent to the peer by us. sent_statements: HashSet<(CompactStatement, ValidatorIndex)>, @@ -149,7 +149,7 @@ struct PeerRelayParentKnowledge { /// How many candidates this peer is aware of for each given validator index. seconded_counts: HashMap<ValidatorIndex, VcPerPeerTracker>, /// How many statements we've received for each candidate that we're aware of. - received_message_count: HashMap<Hash, usize>, + received_message_count: HashMap<CandidateHash, usize>, } impl PeerRelayParentKnowledge { @@ -246,7 +246,7 @@ impl PeerRelayParentKnowledge { { let received_per_candidate = self.received_message_count - .entry(candidate_hash.clone()) + .entry(*candidate_hash) .or_insert(0); if *received_per_candidate >= max_message_count { @@ -372,7 +372,7 @@ enum NotedStatement<'a> { struct ActiveHeadData { /// All candidates we are aware of for this head, keyed by hash. - candidates: HashSet<Hash>, + candidates: HashSet<CandidateHash>, /// Stored statements for circulation to peers. /// /// These are iterable in insertion order, and `Seconded` statements are always @@ -464,7 +464,7 @@ impl ActiveHeadData { } /// Get an iterator over all statements for the active head that are for a particular candidate. - fn statements_about(&self, candidate_hash: Hash) + fn statements_about(&self, candidate_hash: CandidateHash) -> impl Iterator<Item = &'_ StoredStatement> + '_ { self.statements().filter(move |s| s.compact().candidate_hash() == &candidate_hash) @@ -521,10 +521,10 @@ async fn circulate_statement_and_dependents( // First circulate the statement directly to all peers needing it. // The borrow of `active_head` needs to encompass only this (Rust) statement. - let outputs: Option<(Hash, Vec<PeerId>)> = { + let outputs: Option<(CandidateHash, Vec<PeerId>)> = { match active_head.note_statement(statement) { NotedStatement::Fresh(stored) => Some(( - stored.compact().candidate_hash().clone(), + *stored.compact().candidate_hash(), circulate_statement(peers, ctx, relay_parent, stored).await?, )), _ => None, @@ -602,7 +602,7 @@ async fn send_statements_about( peer_data: &mut PeerData, ctx: &mut impl SubsystemContext<Message = StatementDistributionMessage>, relay_parent: Hash, - candidate_hash: Hash, + candidate_hash: CandidateHash, active_head: &ActiveHeadData, metrics: &Metrics, ) -> SubsystemResult<()> { @@ -1110,8 +1110,8 @@ mod tests { #[test] fn note_local_works() { - let hash_a: Hash = [1; 32].into(); - let hash_b: Hash = [2; 32].into(); + let hash_a = CandidateHash([1; 32].into()); + let hash_b = CandidateHash([2; 32].into()); let mut per_peer_tracker = VcPerPeerTracker::default(); per_peer_tracker.note_local(hash_a.clone()); @@ -1126,9 +1126,9 @@ mod tests { #[test] fn note_remote_works() { - let hash_a: Hash = [1; 32].into(); - let hash_b: Hash = [2; 32].into(); - let hash_c: Hash = [3; 32].into(); + let hash_a = CandidateHash([1; 32].into()); + let hash_b = CandidateHash([2; 32].into()); + let hash_c = CandidateHash([3; 32].into()); let mut per_peer_tracker = VcPerPeerTracker::default(); assert!(per_peer_tracker.note_remote(hash_a.clone())); @@ -1148,7 +1148,7 @@ mod tests { fn per_peer_relay_parent_knowledge_send() { let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a: Hash = [1; 32].into(); + let hash_a = CandidateHash([1; 32].into()); // Sending an un-pinned statement should not work and should have no effect. assert!(knowledge.send(&(CompactStatement::Valid(hash_a), 0)).is_none()); @@ -1180,7 +1180,7 @@ mod tests { fn cant_send_after_receiving() { let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a: Hash = [1; 32].into(); + let hash_a = CandidateHash([1; 32].into()); assert!(knowledge.receive(&(CompactStatement::Candidate(hash_a), 0), 3).unwrap()); assert!(knowledge.send(&(CompactStatement::Candidate(hash_a), 0)).is_none()); } @@ -1189,7 +1189,7 @@ mod tests { fn per_peer_relay_parent_knowledge_receive() { let mut knowledge = PeerRelayParentKnowledge::default(); - let hash_a: Hash = [1; 32].into(); + let hash_a = CandidateHash([1; 32].into()); assert_eq!( knowledge.receive(&(CompactStatement::Valid(hash_a), 0), 3), @@ -1226,8 +1226,8 @@ mod tests { assert_eq!(knowledge.received_statements.len(), 3); // number of prior `Ok`s. // Now make sure that the seconding limit is respected. - let hash_b: Hash = [2; 32].into(); - let hash_c: Hash = [3; 32].into(); + let hash_b = CandidateHash([2; 32].into()); + let hash_c = CandidateHash([3; 32].into()); assert_eq!( knowledge.receive(&(CompactStatement::Candidate(hash_b), 0), 3), diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index a506376772d..01e19bc65b5 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -1635,7 +1635,7 @@ mod tests { use std::collections::HashMap; use futures::{executor, pin_mut, select, channel::mpsc, FutureExt}; - use polkadot_primitives::v1::{BlockData, CollatorPair, PoV}; + use polkadot_primitives::v1::{BlockData, CollatorPair, PoV, CandidateHash}; use polkadot_subsystem::messages::RuntimeApiRequest; use polkadot_node_primitives::{Collation, CollationGenerationConfig}; use polkadot_node_network_protocol::{PeerId, ReputationChange, NetworkBridgeEvent}; @@ -2273,7 +2273,7 @@ mod tests { fn test_availability_store_msg() -> AvailabilityStoreMessage { let (sender, _) = oneshot::channel(); - AvailabilityStoreMessage::QueryAvailableData(Default::default(), sender) + AvailabilityStoreMessage::QueryAvailableData(CandidateHash(Default::default()), sender) } fn test_network_bridge_msg() -> NetworkBridgeMessage { diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index ddcec114ebe..45affc5756a 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -28,7 +28,7 @@ use polkadot_primitives::v1::{ Hash, CommittedCandidateReceipt, CandidateReceipt, CompactStatement, EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId, UpwardMessage, ValidationCode, PersistedValidationData, ValidationData, - HeadData, PoV, CollatorPair, Id as ParaId, ValidationOutputs, + HeadData, PoV, CollatorPair, Id as ParaId, ValidationOutputs, CandidateHash, }; use polkadot_statement_table::{ generic::{ @@ -54,10 +54,10 @@ pub enum Statement { Seconded(CommittedCandidateReceipt), /// A statement that a validator has deemed a candidate valid. #[codec(index = "2")] - Valid(Hash), + Valid(CandidateHash), /// A statement that a validator has deemed a candidate invalid. #[codec(index = "3")] - Invalid(Hash), + Invalid(CandidateHash), } impl Statement { diff --git a/polkadot/node/subsystem/src/messages.rs b/polkadot/node/subsystem/src/messages.rs index 7cc078bd3f3..9198d46c5eb 100644 --- a/polkadot/node/subsystem/src/messages.rs +++ b/polkadot/node/subsystem/src/messages.rs @@ -36,7 +36,7 @@ use polkadot_primitives::v1::{ CollatorId, CommittedCandidateReceipt, CoreState, ErasureChunk, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, PersistedValidationData, PoV, SessionIndex, SignedAvailabilityBitfield, - ValidationCode, ValidatorId, ValidationData, + ValidationCode, ValidatorId, ValidationData, CandidateHash, ValidatorIndex, ValidatorSignature, InboundDownwardMessage, }; use std::sync::Arc; @@ -289,31 +289,31 @@ impl BitfieldSigningMessage { #[derive(Debug)] pub enum AvailabilityStoreMessage { /// Query a `AvailableData` from the AV store. - QueryAvailableData(Hash, oneshot::Sender<Option<AvailableData>>), + QueryAvailableData(CandidateHash, oneshot::Sender<Option<AvailableData>>), /// Query whether a `AvailableData` exists within the AV Store. /// /// This is useful in cases when existence /// matters, but we don't want to necessarily pass around multiple /// megabytes of data to get a single bit of information. - QueryDataAvailability(Hash, oneshot::Sender<bool>), + QueryDataAvailability(CandidateHash, oneshot::Sender<bool>), /// Query an `ErasureChunk` from the AV store by the candidate hash and validator index. - QueryChunk(Hash, ValidatorIndex, oneshot::Sender<Option<ErasureChunk>>), + QueryChunk(CandidateHash, ValidatorIndex, oneshot::Sender<Option<ErasureChunk>>), /// Query whether an `ErasureChunk` exists within the AV Store. /// /// This is useful in cases like bitfield signing, when existence /// matters, but we don't want to necessarily pass around large /// quantities of data to get a single bit of information. - QueryChunkAvailability(Hash, ValidatorIndex, oneshot::Sender<bool>), + QueryChunkAvailability(CandidateHash, ValidatorIndex, oneshot::Sender<bool>), /// Store an `ErasureChunk` in the AV store. /// /// Return `Ok(())` if the store operation succeeded, `Err(())` if it failed. StoreChunk { /// A hash of the candidate this chunk belongs to. - candidate_hash: Hash, + candidate_hash: CandidateHash, /// A relevant relay parent. relay_parent: Hash, /// The index of the validator this chunk belongs to. @@ -328,7 +328,7 @@ pub enum AvailabilityStoreMessage { /// If `ValidatorIndex` is present store corresponding chunk also. /// /// Return `Ok(())` if the store operation succeeded, `Err(())` if it failed. - StoreAvailableData(Hash, Option<ValidatorIndex>, u32, AvailableData, oneshot::Sender<Result<(), ()>>), + StoreAvailableData(CandidateHash, Option<ValidatorIndex>, u32, AvailableData, oneshot::Sender<Result<(), ()>>), } impl AvailabilityStoreMessage { diff --git a/polkadot/primitives/src/v0.rs b/polkadot/primitives/src/v0.rs index a01b3c743fa..5f6e3ad544a 100644 --- a/polkadot/primitives/src/v0.rs +++ b/polkadot/primitives/src/v0.rs @@ -633,18 +633,18 @@ pub struct ErasureChunk { pub enum CompactStatement { /// Proposal of a parachain candidate. #[codec(index = "1")] - Candidate(Hash), + Candidate(CandidateHash), /// State that a parachain candidate is valid. #[codec(index = "2")] - Valid(Hash), + Valid(CandidateHash), /// State that a parachain candidate is invalid. #[codec(index = "3")] - Invalid(Hash), + Invalid(CandidateHash), } impl CompactStatement { /// Get the underlying candidate hash this references. - pub fn candidate_hash(&self) -> &Hash { + pub fn candidate_hash(&self) -> &CandidateHash { match *self { CompactStatement::Candidate(ref h) | CompactStatement::Valid(ref h) @@ -684,7 +684,7 @@ impl ValidityAttestation { /// which should be known in context. pub fn signed_payload<H: Encode>( &self, - candidate_hash: Hash, + candidate_hash: CandidateHash, signing_context: &SigningContext<H>, ) -> Vec<u8> { match *self { diff --git a/polkadot/primitives/src/v1.rs b/polkadot/primitives/src/v1.rs index 3533263d208..6b3a2342f1d 100644 --- a/polkadot/primitives/src/v1.rs +++ b/polkadot/primitives/src/v1.rs @@ -31,7 +31,7 @@ pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT}; pub use polkadot_core_primitives::v1::{ BlockNumber, Moment, Signature, AccountPublic, AccountId, AccountIndex, ChainId, Hash, Nonce, Balance, Header, Block, BlockId, UncheckedExtrinsic, - Remark, DownwardMessage, InboundDownwardMessage, + Remark, DownwardMessage, InboundDownwardMessage, CandidateHash, }; // Export some polkadot-parachain primitives @@ -148,8 +148,8 @@ impl<H> CandidateReceipt<H> { } /// Computes the blake2-256 hash of the receipt. - pub fn hash(&self) -> Hash where H: Encode { - BlakeTwo256::hash_of(self) + pub fn hash(&self) -> CandidateHash where H: Encode { + CandidateHash(BlakeTwo256::hash_of(self)) } } @@ -196,7 +196,7 @@ impl<H: Clone> CommittedCandidateReceipt<H> { /// /// This computes the canonical hash, not the hash of the directly encoded data. /// Thus this is a shortcut for `candidate.to_plain().hash()`. - pub fn hash(&self) -> Hash where H: Encode { + pub fn hash(&self) -> CandidateHash where H: Encode { self.to_plain().hash() } } @@ -421,7 +421,7 @@ pub fn check_candidate_backing<H: AsRef<[u8]> + Clone + Encode>( } // this is known, even in runtime, to be blake2-256. - let hash: Hash = backed.candidate.hash(); + let hash = backed.candidate.hash(); let mut signed = 0; for ((val_in_group_idx, _), attestation) in backed.validator_indices.iter().enumerate() diff --git a/polkadot/roadmap/implementers-guide/src/types/network.md b/polkadot/roadmap/implementers-guide/src/types/network.md index 75f251613f2..a5472a40715 100644 --- a/polkadot/roadmap/implementers-guide/src/types/network.md +++ b/polkadot/roadmap/implementers-guide/src/types/network.md @@ -23,7 +23,7 @@ enum ObservedRole { ```rust enum AvailabilityDistributionV1Message { /// An erasure chunk for a given candidate hash. - Chunk(Hash, ErasureChunk), + Chunk(CandidateHash, ErasureChunk), } ``` diff --git a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md index 484d53b70f4..e0ab023a16d 100644 --- a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -136,18 +136,18 @@ Messages to and from the availability store. ```rust enum AvailabilityStoreMessage { /// Query the `AvailableData` of a candidate by hash. - QueryAvailableData(Hash, ResponseChannel<Option<AvailableData>>), + QueryAvailableData(CandidateHash, ResponseChannel<Option<AvailableData>>), /// Query whether an `AvailableData` exists within the AV Store. - QueryDataAvailability(Hash, ResponseChannel<bool>), + QueryDataAvailability(CandidateHash, ResponseChannel<bool>), /// Query a specific availability chunk of the candidate's erasure-coding by validator index. /// Returns the chunk and its inclusion proof against the candidate's erasure-root. - QueryChunk(Hash, ValidatorIndex, ResponseChannel<Option<AvailabilityChunkAndProof>>), + QueryChunk(CandidateHash, ValidatorIndex, ResponseChannel<Option<AvailabilityChunkAndProof>>), /// Store a specific chunk of the candidate's erasure-coding by validator index, with an /// accompanying proof. - StoreChunk(Hash, ValidatorIndex, AvailabilityChunkAndProof, ResponseChannel<Result<()>>), + StoreChunk(CandidateHash, ValidatorIndex, AvailabilityChunkAndProof, ResponseChannel<Result<()>>), /// Store `AvailableData`. If `ValidatorIndex` is provided, also store this validator's /// `AvailabilityChunkAndProof`. - StoreAvailableData(Hash, Option<ValidatorIndex>, u32, AvailableData, ResponseChannel<Result<()>>), + StoreAvailableData(CandidateHash, Option<ValidatorIndex>, u32, AvailableData, ResponseChannel<Result<()>>), } ``` diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs index fed60ded0da..a00b582b7dc 100644 --- a/polkadot/statement-table/src/lib.rs +++ b/polkadot/statement-table/src/lib.rs @@ -18,63 +18,21 @@ pub mod generic; pub use generic::{Table, Context}; -/// Concrete instantiations suitable for v0 primitives. -pub mod v0 { - use crate::generic; - use primitives::v0::{ - Hash, - Id, AbridgedCandidateReceipt, CompactStatement as PrimitiveStatement, ValidatorSignature, ValidatorIndex, - }; - - /// Statements about candidates on the network. - pub type Statement = generic::Statement<AbridgedCandidateReceipt, Hash>; - - /// Signed statements about candidates. - pub type SignedStatement = generic::SignedStatement< - AbridgedCandidateReceipt, - Hash, - ValidatorIndex, - ValidatorSignature, - >; - - /// Kinds of misbehavior, along with proof. - pub type Misbehavior = generic::Misbehavior< - AbridgedCandidateReceipt, - Hash, - ValidatorIndex, - ValidatorSignature, - >; - - /// A summary of import of a statement. - pub type Summary = generic::Summary<Hash, Id>; - - impl<'a> From<&'a Statement> for PrimitiveStatement { - fn from(s: &'a Statement) -> PrimitiveStatement { - match *s { - generic::Statement::Valid(s) => PrimitiveStatement::Valid(s), - generic::Statement::Invalid(s) => PrimitiveStatement::Invalid(s), - generic::Statement::Candidate(ref s) => PrimitiveStatement::Candidate(s.hash()), - } - } - } -} - /// Concrete instantiations suitable for v1 primitives. pub mod v1 { use crate::generic; use primitives::v1::{ - Hash, - Id, CommittedCandidateReceipt, CompactStatement as PrimitiveStatement, + CandidateHash, Id, CommittedCandidateReceipt, CompactStatement as PrimitiveStatement, ValidatorSignature, ValidatorIndex, }; /// Statements about candidates on the network. - pub type Statement = generic::Statement<CommittedCandidateReceipt, Hash>; + pub type Statement = generic::Statement<CommittedCandidateReceipt, CandidateHash>; /// Signed statements about candidates. pub type SignedStatement = generic::SignedStatement< CommittedCandidateReceipt, - Hash, + CandidateHash, ValidatorIndex, ValidatorSignature, >; @@ -82,13 +40,13 @@ pub mod v1 { /// Kinds of misbehavior, along with proof. pub type Misbehavior = generic::Misbehavior< CommittedCandidateReceipt, - Hash, + CandidateHash, ValidatorIndex, ValidatorSignature, >; /// A summary of import of a statement. - pub type Summary = generic::Summary<Hash, Id>; + pub type Summary = generic::Summary<CandidateHash, Id>; impl<'a> From<&'a Statement> for PrimitiveStatement { fn from(s: &'a Statement) -> PrimitiveStatement { -- GitLab