authority_selection_inherents/
lib.rs

1//! # Partner Chain Committee Selection
2//!
3//! Inherent data provider and selection logic for Partner Chain committee selection.
4//!
5//! ## Overview
6//!
7//! This crate provides an IDP and all types necessary for a Partner Chain to select
8//! block producer committees using data sourced from Cardano smart contracts.
9//!
10//! ## Usage
11//!
12//! ### Prerequisites
13//!
14//! This crate is intended to work with `pallet_session_validator_management`. See
15//! the pallet's documentation for instructions how to add it to you runtime. Your
16//! pallet should be configured with [CommitteeMember] as its `CommitteeMember`,
17//! using the `CrossChainPublic` and `SessionKeys` defined described in the pallet's
18//! documentation.
19//!
20//! Additionally [AriadneInherentDataProvider] needs access to a data source
21//! implementing [AuthoritySelectionDataSource]. A Db-Sync-based implementation is
22//! provided by the `partner_chains_db_sync_data_sources` crate.
23//!
24//! ### Adding to the node
25//!
26//! #### Implementing runtime API
27//!
28//! Implement the [SessionValidatorManagementApi] for your runtime. Each API method has
29//! a corresponding method in the pallet that should be used for that purpose. Refer to
30//! the demo runtime for an example.
31//!
32//! #### Add the inherent data provider
33//!
34//! Wire the [AriadneInherentDataProvider] into your inherent data provider stack. The same
35//! constructor [AriadneInherentDataProvider::new] should be used for both proposing and
36//! validating blocks. Refer to the demo node implementation for an example of how to wire
37//! it correctly into a node.
38//!
39#![cfg_attr(not(feature = "std"), no_std)]
40#![deny(missing_docs)]
41
42extern crate alloc;
43
44use scale_info::TypeInfo;
45use serde::{Deserialize, Serialize};
46use sidechain_domain::{CandidateKeys, StakePoolPublicKey};
47use sp_core::{ConstU32, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
48use sp_runtime::traits::OpaqueKeys;
49use sp_session_validator_management::CommitteeMember as CommitteeMemberT;
50
51mod ariadne_inherent_data_provider;
52mod authority_selection_inputs;
53mod filter_invalid_candidates;
54mod select_authorities;
55
56pub use {
57	ariadne_inherent_data_provider::AriadneInherentDataProvider,
58	authority_selection_inputs::{AriadneParameters, AuthoritySelectionInputs},
59	filter_invalid_candidates::{
60		PermissionedCandidateDataError, RegisterValidatorSignedMessage, RegistrationDataError,
61		StakeError, filter_trustless_candidates_registrations,
62		runtime_decl_for_candidate_validation_api, validate_permissioned_candidate_data,
63		validate_registration_data, validate_stake,
64	},
65	select_authorities::select_authorities,
66};
67#[cfg(feature = "std")]
68pub use {
69	authority_selection_inputs::AuthoritySelectionDataSource,
70	filter_invalid_candidates::CandidateValidationApi,
71};
72
73#[cfg(test)]
74mod runtime_api_mock;
75#[cfg(test)]
76mod tests;
77
78#[cfg(any(test, feature = "mock"))]
79pub mod mock;
80
81#[derive(
82	Serialize,
83	Deserialize,
84	Clone,
85	Encode,
86	Decode,
87	DecodeWithMemTracking,
88	TypeInfo,
89	MaxEncodedLen,
90	Debug,
91	PartialEq,
92	Eq,
93)]
94/// Type representing committee members, either permissioned or registered
95pub enum CommitteeMember<AuthorityId, AuthorityKeys> {
96	/// A permissioned candidate
97	Permissioned {
98		/// Authority id of the candidate
99		id: AuthorityId,
100		/// Authority keys of the candidate
101		keys: AuthorityKeys,
102	},
103	/// A registered candidate
104	Registered {
105		/// Authority id of the candidate
106		id: AuthorityId,
107		/// Authority keys of the candidate
108		keys: AuthorityKeys,
109		/// Stake pool pub key of the candidate
110		stake_pool_pub_key: StakePoolPublicKey,
111	},
112}
113
114impl<AuthorityId, AuthorityKeys> From<(AuthorityId, AuthorityKeys)>
115	for CommitteeMember<AuthorityId, AuthorityKeys>
116{
117	fn from((id, keys): (AuthorityId, AuthorityKeys)) -> Self {
118		Self::Permissioned { id, keys }
119	}
120}
121
122impl<AuthorityId, AuthorityKeys> CommitteeMember<AuthorityId, AuthorityKeys> {
123	/// Constructs new permissioned candidate
124	pub fn permissioned(id: AuthorityId, keys: AuthorityKeys) -> Self {
125		Self::Permissioned { id, keys }
126	}
127}
128
129impl<AuthorityId: Clone, AuthorityKeys: Clone> CommitteeMemberT
130	for CommitteeMember<AuthorityId, AuthorityKeys>
131{
132	type AuthorityId = AuthorityId;
133	type AuthorityKeys = AuthorityKeys;
134
135	fn authority_id(&self) -> AuthorityId {
136		match self {
137			Self::Permissioned { id, .. } => id.clone(),
138			Self::Registered { id, .. } => id.clone(),
139		}
140	}
141
142	fn authority_keys(&self) -> AuthorityKeys {
143		match self {
144			Self::Permissioned { keys, .. } => keys.clone(),
145			Self::Registered { keys, .. } => keys.clone(),
146		}
147	}
148}
149
150/// Trait to try extract implementing type from [CandidateKeys].
151pub trait MaybeFromCandidateKeys: OpaqueKeys + Decode + Sized {
152	/// Depends on `Decode` that is derived by `impl_opaque_keys!`
153	fn maybe_from(keys: &CandidateKeys) -> Option<Self> {
154		let required_keys = Self::key_ids();
155
156		let mut encoded_keys = sp_runtime::BoundedVec::<u8, ConstU32<1024>>::new();
157		for key_id in required_keys {
158			let key = keys.0.iter().find(|key| key.id == key_id.0)?;
159			encoded_keys.try_append(&mut key.bytes.clone()).ok()?;
160		}
161		Self::decode(&mut &encoded_keys[..]).ok()
162	}
163}