From b6632790aae50f3bf714f4180aba1f2f65fe6fb0 Mon Sep 17 00:00:00 2001 From: Nikolaos Dymitriadis Date: Wed, 19 Feb 2025 10:25:24 +0100 Subject: [PATCH] change: include candidate type and MC pkey in committee data Signed-off-by: Nikolaos Dymitriadis --- dev/local-environment/setup.sh | 2 +- node/node/src/inherent_data.rs | 14 +- node/node/src/rpc.rs | 10 +- node/node/src/tests/runtime_api_mock.rs | 11 +- node/runtime/src/lib.rs | 26 ++-- toolkit/cli/node-commands/src/lib.rs | 11 +- .../session-validator-management/src/lib.rs | 30 +---- .../src/ariadne_inherent_data_provider.rs | 21 +-- .../src/runtime_api_mock.rs | 4 +- toolkit/primitives/session-manager/src/lib.rs | 5 +- .../src/pallet_session_support.rs | 2 +- .../session-validator-management/Cargo.toml | 5 +- .../query/Cargo.toml | 1 + .../query/src/get_registrations.rs | 8 +- .../query/src/lib.rs | 120 +++++++++++++----- .../query/src/tests/mod.rs | 6 +- .../query/src/tests/runtime_api_mock.rs | 14 +- .../query/src/types/mod.rs | 29 ++++- .../session-validator-management/src/lib.rs | 28 +++- 19 files changed, 208 insertions(+), 139 deletions(-) diff --git a/dev/local-environment/setup.sh b/dev/local-environment/setup.sh index ea04375b4..9f8144444 100755 --- a/dev/local-environment/setup.sh +++ b/dev/local-environment/setup.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -PARTNER_CHAINS_NODE_IMAGE="ghcr.io/input-output-hk/partner-chains/partner-chains-node:v1.5.0" +PARTNER_CHAINS_NODE_IMAGE="ghcr.io/input-output-hk/partner-chains/partner-chains-node:7c6cb681fee47c2ac1e4339822b7a8382f7ee55d" CARDANO_IMAGE="ghcr.io/intersectmbo/cardano-node:10.1.4" DBSYNC_IMAGE="ghcr.io/intersectmbo/cardano-db-sync:13.6.0.4" OGMIOS_IMAGE="cardanosolutions/ogmios:v6.11.0" diff --git a/node/node/src/inherent_data.rs b/node/node/src/inherent_data.rs index 150336d77..b06f46cf7 100644 --- a/node/node/src/inherent_data.rs +++ b/node/node/src/inherent_data.rs @@ -2,6 +2,7 @@ use authority_selection_inherents::ariadne_inherent_data_provider::AriadneInhere use authority_selection_inherents::authority_selection_inputs::{ AuthoritySelectionDataSource, AuthoritySelectionInputs, }; +use authority_selection_inherents::CommitteeMember; use derive_new::new; use jsonrpsee::core::async_trait; use sc_consensus_aura::{find_pre_digest, SlotDuration}; @@ -10,10 +11,9 @@ use sidechain_domain::mainchain_epoch::MainchainEpochConfig; use sidechain_domain::{McBlockHash, ScEpochNumber}; use sidechain_mc_hash::McHashDataSource; use sidechain_mc_hash::McHashInherentDataProvider as McHashIDP; -use sidechain_runtime::{ - opaque::{Block, SessionKeys}, - BeneficiaryId, CrossChainPublic, -}; +use sidechain_runtime::opaque::SessionKeys; +use sidechain_runtime::CrossChainPublic; +use sidechain_runtime::{opaque::Block, BeneficiaryId}; use sidechain_slots::ScSlotConfig; use sp_api::ProvideRuntimeApi; use sp_block_production_log::BlockProducerIdInherentProvider; @@ -51,8 +51,7 @@ where T: HeaderBackend, T::Api: SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, @@ -149,8 +148,7 @@ where T: ProvideRuntimeApi + Send + Sync + HeaderBackend, T::Api: SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, diff --git a/node/node/src/rpc.rs b/node/node/src/rpc.rs index 0da0da938..4d6ac0d80 100644 --- a/node/node/src/rpc.rs +++ b/node/node/src/rpc.rs @@ -6,8 +6,10 @@ #![warn(missing_docs)] use crate::main_chain_follower::DataSources; -use authority_selection_inherents::authority_selection_inputs::AuthoritySelectionInputs; use authority_selection_inherents::filter_invalid_candidates::CandidateValidationApi; +use authority_selection_inherents::{ + authority_selection_inputs::AuthoritySelectionInputs, CommitteeMember, +}; use jsonrpsee::RpcModule; use pallet_session_validator_management_rpc::*; use pallet_sidechain_rpc::*; @@ -19,12 +21,11 @@ use sc_rpc::SubscriptionTaskExecutor; use sc_transaction_pool_api::TransactionPool; use sidechain_domain::mainchain_epoch::MainchainEpochConfig; use sidechain_domain::ScEpochNumber; -use sidechain_runtime::CrossChainPublic; use sidechain_runtime::{ opaque::{Block, SessionKeys}, AccountId, Balance, Nonce, }; -use sidechain_runtime::{BlockNumber, Hash}; +use sidechain_runtime::{BlockNumber, CrossChainPublic, Hash}; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; @@ -77,8 +78,7 @@ where C::Api: sp_sidechain::GetSidechainStatus, C::Api: sp_session_validator_management::SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, diff --git a/node/node/src/tests/runtime_api_mock.rs b/node/node/src/tests/runtime_api_mock.rs index a7dfb6678..bb0fd1924 100644 --- a/node/node/src/tests/runtime_api_mock.rs +++ b/node/node/src/tests/runtime_api_mock.rs @@ -1,5 +1,6 @@ use super::mock::mock_genesis_utxo; use authority_selection_inherents::authority_selection_inputs::AuthoritySelectionInputs; +use authority_selection_inherents::CommitteeMember; use sidechain_domain::*; use sidechain_mc_hash::McHashInherentDigest; use sidechain_runtime::opaque::SessionKeys; @@ -58,25 +59,25 @@ sp_api::mock_impl_runtime_apis! { fn genesis_utxo() -> UtxoId { mock_genesis_utxo() } } - impl sp_session_validator_management::SessionValidatorManagementApi for TestApi { - fn get_current_committee() -> (ScEpochNumber, Vec) { + impl sp_session_validator_management::SessionValidatorManagementApi, AuthoritySelectionInputs, ScEpochNumber> for TestApi { + fn get_current_committee() -> (ScEpochNumber, Vec>) { unimplemented!() } fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber { self.next_unset_epoch_number } - fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, _sidechain_epoch: sidechain_domain::ScEpochNumber) -> Option> { + fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, _sidechain_epoch: sidechain_domain::ScEpochNumber) -> Option>> { if authority_selection_inputs.registered_candidates.is_empty() { None } else { - let result: Vec<(CrossChainPublic, SessionKeys)> = authority_selection_inputs.registered_candidates.into_iter().map(|candidate| { + let result = authority_selection_inputs.registered_candidates.into_iter().map(|candidate| { let registration = candidate.registrations().first().unwrap().clone(); let cross_chain_pub_slice: [u8; 33] = registration.cross_chain_pub_key.0.try_into().unwrap(); let cross_chain_public: CrossChainPublic = CrossChainPublic::from(ecdsa::Public::from(cross_chain_pub_slice)); let aura_pub_key = registration.aura_pub_key.try_into_sr25519().unwrap(); let grandpa_pub_key = registration.grandpa_pub_key.try_into_ed25519().unwrap(); let session_keys = (aura_pub_key, grandpa_pub_key).into(); - (cross_chain_public, session_keys) + CommitteeMember::permissioned(cross_chain_public, session_keys) }).collect(); Some(result) } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index ed6626bef..9989d713f 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -14,6 +14,7 @@ use authority_selection_inherents::filter_invalid_candidates::{ StakeError, }; use authority_selection_inherents::select_authorities::select_authorities; +use authority_selection_inherents::CommitteeMember; use frame_support::genesis_builder_helper::{build_state, get_preset}; use frame_support::weights::constants::RocksDbWeight as RuntimeDbWeight; use frame_support::BoundedVec; @@ -43,7 +44,6 @@ use sp_runtime::{ transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, DispatchResult, MultiSignature, Perbill, }; -use sp_session_validator_management::CommitteeMember; use sp_sidechain::SidechainStatus; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -398,8 +398,7 @@ impl pallet_session_validator_management::Config for Runtime { type AuthoritySelectionInputs = AuthoritySelectionInputs; type ScEpochNumber = ScEpochNumber; type WeightInfo = pallet_session_validator_management::weights::SubstrateWeight; - type CommitteeMember = - authority_selection_inherents::CommitteeMember; + type CommitteeMember = CommitteeMember; fn select_authorities( input: AuthoritySelectionInputs, @@ -828,23 +827,24 @@ impl_runtime_apis! { } } - impl sp_session_validator_management::SessionValidatorManagementApi for Runtime { - fn get_current_committee() -> (ScEpochNumber, Vec) { + #[api_version(2)] + impl sp_session_validator_management::SessionValidatorManagementApi< + Block, + CommitteeMember, + AuthoritySelectionInputs, + sidechain_domain::ScEpochNumber + > for Runtime { + fn get_current_committee() -> (ScEpochNumber, Vec>) { SessionCommitteeManagement::get_current_committee() } - fn get_next_committee() -> Option<(ScEpochNumber, Vec)> { + fn get_next_committee() -> Option<(ScEpochNumber, Vec>)> { SessionCommitteeManagement::get_next_committee() } fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber { SessionCommitteeManagement::get_next_unset_epoch_number() } - fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber) -> Option> { - Some( - SessionCommitteeManagement::calculate_committee(authority_selection_inputs, sidechain_epoch)? - .into_iter() - .map(|member| (member.authority_id(), member.authority_keys())) - .collect() - ) + fn calculate_committee(authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber) -> Option>> { + SessionCommitteeManagement::calculate_committee(authority_selection_inputs, sidechain_epoch) } fn get_main_chain_scripts() -> sp_session_validator_management::MainChainScripts { SessionCommitteeManagement::get_main_chain_scripts() diff --git a/toolkit/cli/node-commands/src/lib.rs b/toolkit/cli/node-commands/src/lib.rs index 0f06ec4cb..c5c373af2 100644 --- a/toolkit/cli/node-commands/src/lib.rs +++ b/toolkit/cli/node-commands/src/lib.rs @@ -15,6 +15,7 @@ use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_runtime::traits::Block as BlockT; use sp_runtime::AccountId32; +use sp_session_validator_management::CommitteeMember as CommitteeMemberT; use sp_session_validator_management::SessionValidatorManagementApi; use sp_session_validator_management_query::commands::*; use sp_session_validator_management_query::SessionValidatorManagementQuery; @@ -102,7 +103,7 @@ pub enum PartnerChainsSubcommand { Wizards(partner_chains_cli::Command), } -pub fn run( +pub fn run( cli: &Cli, get_deps: impl FnOnce( sc_service::Configuration, @@ -119,15 +120,15 @@ where + GetSidechainStatus + SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, > + CandidateValidationApi, Block: BlockT, NumberFor: From + Into, - SessionKeys: Decode + Send + Sync + 'static, - CrossChainPublic: Decode + Encode + AsRef<[u8]> + Send + Sync + 'static, + CommitteeMember: CommitteeMemberT + Encode + Decode + Send + Sync + 'static, + CommitteeMember::AuthorityId: Decode + Encode + AsRef<[u8]> + Send + Sync + 'static, + CommitteeMember::AuthorityKeys: Decode + Encode, { match cmd { PartnerChainsSubcommand::SidechainParams(cmd) => { diff --git a/toolkit/pallets/session-validator-management/src/lib.rs b/toolkit/pallets/session-validator-management/src/lib.rs index a03430c9e..bb23e98b7 100644 --- a/toolkit/pallets/session-validator-management/src/lib.rs +++ b/toolkit/pallets/session-validator-management/src/lib.rs @@ -354,16 +354,12 @@ pub mod pallet { T::select_authorities(authority_selection_inputs, sidechain_epoch).map(|c| c.to_vec()) } - pub fn rotate_committee_to_next_epoch() -> Option> { + pub fn rotate_committee_to_next_epoch() -> Option> { let next_committee = NextCommittee::::take()?; CurrentCommittee::::put(next_committee.clone()); - let validators: Vec<(T::AccountId, T::AuthorityKeys)> = next_committee - .committee - .into_iter() - .map(|member| (member.authority_id().into(), member.authority_keys())) - .collect(); + let validators = next_committee.committee.to_vec(); let len = validators.len(); info!( "Committee rotated: Returning {len} validators, stored in epoch {}", @@ -372,28 +368,14 @@ pub mod pallet { Some(validators) } - pub fn get_current_committee() -> (T::ScEpochNumber, Vec) { + pub fn get_current_committee() -> (T::ScEpochNumber, Vec) { let committee_info = CurrentCommittee::::get(); - ( - committee_info.epoch, - committee_info - .committee - .into_iter() - .map(|member| member.authority_id()) - .collect(), - ) + (committee_info.epoch, committee_info.committee.to_vec()) } - pub fn get_next_committee() -> Option<(T::ScEpochNumber, Vec)> { + pub fn get_next_committee() -> Option<(T::ScEpochNumber, Vec)> { let committee_info = NextCommittee::::get()?; - Some(( - committee_info.epoch, - committee_info - .committee - .into_iter() - .map(|member| member.authority_id()) - .collect(), - )) + Some((committee_info.epoch, committee_info.committee.to_vec())) } pub fn get_main_chain_scripts() -> MainChainScripts { diff --git a/toolkit/primitives/authority-selection-inherents/src/ariadne_inherent_data_provider.rs b/toolkit/primitives/authority-selection-inherents/src/ariadne_inherent_data_provider.rs index f5d672f90..28694baf0 100644 --- a/toolkit/primitives/authority-selection-inherents/src/ariadne_inherent_data_provider.rs +++ b/toolkit/primitives/authority-selection-inherents/src/ariadne_inherent_data_provider.rs @@ -2,6 +2,7 @@ use crate::authority_selection_inputs::AuthoritySelectionDataSource; use crate::authority_selection_inputs::AuthoritySelectionInputs; use parity_scale_codec::{Decode, Encode}; +use sp_session_validator_management::CommitteeMember as CommitteeMemberT; #[cfg(feature = "std")] use { crate::authority_selection_inputs::AuthoritySelectionInputsCreationError, @@ -40,7 +41,7 @@ impl AriadneInherentDataProvider { }) } - pub async fn new( + pub async fn new( client: &T, sc_slot_config: &ScSlotConfig, mc_epoch_config: &MainchainEpochConfig, @@ -50,14 +51,14 @@ impl AriadneInherentDataProvider { mc_reference_epoch: McEpochNumber, ) -> Result where - SessionKeys: Decode, - CrossChainPublic: Decode + Encode, + CommitteeMember: CommitteeMemberT + Decode + Encode, + CommitteeMember::AuthorityKeys: Decode + Encode, + CommitteeMember::AuthorityId: Decode + Encode, Block: BlockT, T: ProvideRuntimeApi + Send + Sync, T::Api: SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, @@ -103,7 +104,7 @@ pub enum InherentProviderCreationError { } #[cfg(feature = "std")] -fn mc_epoch_for_next_ariadne_cidp( +fn mc_epoch_for_next_ariadne_cidp( client: &T, sc_slot_config: &ScSlotConfig, epoch_config: &MainchainEpochConfig, @@ -112,13 +113,13 @@ fn mc_epoch_for_next_ariadne_cidp( ) -> Result where Block: BlockT, - SessionKeys: Decode, - CrossChainPublic: Decode + Encode, + CommitteeMember: Decode + Encode + CommitteeMemberT, + CommitteeMember::AuthorityKeys: Decode + Encode, + CommitteeMember::AuthorityId: Decode + Encode, T: ProvideRuntimeApi + Send + Sync, T::Api: SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, diff --git a/toolkit/primitives/authority-selection-inherents/src/runtime_api_mock.rs b/toolkit/primitives/authority-selection-inherents/src/runtime_api_mock.rs index c416e36a6..c514e94fb 100644 --- a/toolkit/primitives/authority-selection-inherents/src/runtime_api_mock.rs +++ b/toolkit/primitives/authority-selection-inherents/src/runtime_api_mock.rs @@ -21,10 +21,10 @@ impl sp_api::ProvideRuntimeApi for TestApi { } sp_api::mock_impl_runtime_apis! { - impl SessionValidatorManagementApi + impl SessionValidatorManagementApi for TestApi { - fn get_current_committee() -> (ScEpochNumber, Vec) { + fn get_current_committee() -> (ScEpochNumber, Vec<(CrossChainPublicKey, AccountKeys)>) { unimplemented!() } fn get_next_unset_epoch_number() -> sidechain_domain::ScEpochNumber { diff --git a/toolkit/primitives/session-manager/src/lib.rs b/toolkit/primitives/session-manager/src/lib.rs index 4ea37f07c..d07e7b00f 100644 --- a/toolkit/primitives/session-manager/src/lib.rs +++ b/toolkit/primitives/session-manager/src/lib.rs @@ -43,7 +43,10 @@ impl .expect( "Session should never end without current epoch validators defined. \ Check ShouldEndSession implementation or if it is used before starting new session", - ), + ) + .into_iter() + .map(|member| (member.authority_id().into(), member.authority_keys())) + .collect(), ) } diff --git a/toolkit/primitives/session-manager/src/pallet_session_support.rs b/toolkit/primitives/session-manager/src/pallet_session_support.rs index 386aabf3a..dd441437e 100644 --- a/toolkit/primitives/session-manager/src/pallet_session_support.rs +++ b/toolkit/primitives/session-manager/src/pallet_session_support.rs @@ -39,7 +39,7 @@ impl pallet_session_validator_management::Pallet::::rotate_committee_to_next_epoch() .expect( "PalletSessionSupport: Session should never end without current epoch validators defined. This may be caused by ShouldEndSession invalid behavior or being called before starting new session", - ).into_iter().map(|(id, _)| id).collect::>(), + ).into_iter().map(|member| member.authority_id().into()).collect::>(), ) } diff --git a/toolkit/primitives/session-validator-management/Cargo.toml b/toolkit/primitives/session-validator-management/Cargo.toml index 809c85144..13151fd4e 100644 --- a/toolkit/primitives/session-validator-management/Cargo.toml +++ b/toolkit/primitives/session-validator-management/Cargo.toml @@ -28,8 +28,11 @@ std = [ "sp-inherents/std", "sp-std/std", "sp-runtime/std", + "sidechain-domain/std", + "sidechain-domain/serde", "thiserror", - "envy" + "envy", + "serde" ] serde = [ "dep:serde", diff --git a/toolkit/primitives/session-validator-management/query/Cargo.toml b/toolkit/primitives/session-validator-management/query/Cargo.toml index 27f6d02ba..2e40c32f8 100644 --- a/toolkit/primitives/session-validator-management/query/Cargo.toml +++ b/toolkit/primitives/session-validator-management/query/Cargo.toml @@ -29,3 +29,4 @@ hex-literal = { workspace = true } minicbor = { workspace = true } plutus-datum-derive = { workspace = true } tokio = { workspace = true } +authority-selection-inherents = { workspace = true, features = ["mock"] } diff --git a/toolkit/primitives/session-validator-management/query/src/get_registrations.rs b/toolkit/primitives/session-validator-management/query/src/get_registrations.rs index f19995590..5f4ad8b6a 100644 --- a/toolkit/primitives/session-validator-management/query/src/get_registrations.rs +++ b/toolkit/primitives/session-validator-management/query/src/get_registrations.rs @@ -9,12 +9,8 @@ use sidechain_domain::{ use sp_core::bytes::to_hex; use sp_sidechain::GetGenesisUtxo; -impl< - C, - Block, - SessionKeys: parity_scale_codec::Decode + Send + Sync + 'static, - CrossChainPublic, - > SessionValidatorManagementQuery +impl + SessionValidatorManagementQuery where Block: BlockT, C: HeaderBackend, diff --git a/toolkit/primitives/session-validator-management/query/src/lib.rs b/toolkit/primitives/session-validator-management/query/src/lib.rs index b41a10163..78d5c0944 100644 --- a/toolkit/primitives/session-validator-management/query/src/lib.rs +++ b/toolkit/primitives/session-validator-management/query/src/lib.rs @@ -8,14 +8,17 @@ use authority_selection_inherents::authority_selection_inputs::{ }; use authority_selection_inherents::filter_invalid_candidates::CandidateValidationApi; use derive_new::new; +use parity_scale_codec::{Decode, Encode}; use sidechain_block_search::{predicates::AnyBlockInEpoch, FindSidechainBlock, SidechainInfo}; use sidechain_domain::{McEpochNumber, ScEpochNumber, StakePoolPublicKey}; -use sp_api::ProvideRuntimeApi; +use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_blockchain::{HeaderBackend, Info}; use sp_core::bytes::to_hex; use sp_runtime::traits::NumberFor; use sp_runtime::traits::{Block as BlockT, Zero}; -use sp_session_validator_management::SessionValidatorManagementApi; +use sp_session_validator_management::{ + CommitteeMember as CommitteeMemberT, SessionValidatorManagementApi, +}; use sp_sidechain::{GetGenesisUtxo, GetSidechainStatus}; use std::sync::Arc; use types::*; @@ -48,33 +51,87 @@ pub trait SessionValidatorManagementQueryApi { } #[derive(new)] -pub struct SessionValidatorManagementQuery< - C, - Block, - SessionKeys: parity_scale_codec::Decode, - CrossChainPublic, -> { +pub struct SessionValidatorManagementQuery { client: Arc, candidate_data_source: Arc, - _marker: std::marker::PhantomData<(Block, SessionKeys, CrossChainPublic)>, + _marker: std::marker::PhantomData<(Block, CommitteeMember)>, } -#[async_trait] -impl< - C, +impl SessionValidatorManagementQuery +where + Block: BlockT, + C: ProvideRuntimeApi, + C::Api: sp_api::Core + ApiExt, + CommitteeMember: CommitteeMemberT + Encode + Decode, + CommitteeMember::AuthorityId: Encode + Decode + AsRef<[u8]>, + CommitteeMember::AuthorityKeys: Encode + Decode, + AuthoritySelectionInputs: Encode + Decode, + C::Api: SessionValidatorManagementApi< Block, - SessionKeys: parity_scale_codec::Decode + Send + Sync + 'static, - CrossChainPublic: parity_scale_codec::Decode - + parity_scale_codec::Encode - + AsRef<[u8]> - + Send - + Sync - + 'static, - > SessionValidatorManagementQueryApi - for SessionValidatorManagementQuery + CommitteeMember, + AuthoritySelectionInputs, + ScEpochNumber, + >, +{ + fn validator_management_api_version(&self, block: Block::Hash) -> QueryResult { + let version = (self.client.runtime_api()) + .api_version::>(block) + .map_err(err_debug)? + .unwrap_or(1); + Ok(version) + } + + fn get_current_committee_versioned( + &self, + block: Block::Hash, + ) -> QueryResult { + let api = self.client.runtime_api(); + + if self.validator_management_api_version(block)? < 2 { + #[allow(deprecated)] + let (epoch, authority_ids) = + api.get_current_committee_before_version_2(block).map_err(err_debug)?; + Ok(GetCommitteeResponse::new_legacy(epoch, authority_ids)) + } else { + let (epoch, authority_data) = api.get_current_committee(block).map_err(err_debug)?; + Ok(GetCommitteeResponse::new(epoch, authority_data)) + } + } + + fn get_next_committee_versioned( + &self, + block: Block::Hash, + ) -> QueryResult> { + let api = self.client.runtime_api(); + + if self.validator_management_api_version(block)? < 2 { + #[allow(deprecated)] + Ok(api.get_next_committee_before_version_2(block).map_err(err_debug)?.map( + |(epoch, authority_ids)| GetCommitteeResponse::new_legacy(epoch, authority_ids), + )) + } else { + Ok(api + .get_next_committee(block) + .map_err(err_debug)? + .map(|(epoch, authority_data)| GetCommitteeResponse::new(epoch, authority_data))) + } + } +} + +#[async_trait] +impl SessionValidatorManagementQueryApi + for SessionValidatorManagementQuery where Block: BlockT, NumberFor: From + Into, + CommitteeMember: CommitteeMemberT + Decode + Encode + Send + Sync + 'static, + CommitteeMember::AuthorityKeys: Decode + Encode, + CommitteeMember::AuthorityId: AsRef<[u8]> + Decode + Encode + Send + Sync + 'static, C: Send + Sync + 'static, C: ProvideRuntimeApi, C: HeaderBackend, @@ -82,8 +139,7 @@ where C::Api: GetSidechainStatus, C::Api: SessionValidatorManagementApi< Block, - SessionKeys, - CrossChainPublic, + CommitteeMember, AuthoritySelectionInputs, ScEpochNumber, >, @@ -95,10 +151,8 @@ where let Info { genesis_hash, best_number: latest_block, best_hash, .. } = self.client.info(); if epoch_number.is_zero() { - let (_, genesis_committee) = (self.client.runtime_api()) - .get_current_committee(genesis_hash) - .map_err(err_debug)?; - return Ok(GetCommitteeResponse::new(epoch_number, genesis_committee)); + let genesis_committee = self.get_current_committee_versioned(genesis_hash)?; + return Ok(GetCommitteeResponse { sidechain_epoch: 0, ..genesis_committee }); } let first_epoch = { @@ -123,20 +177,16 @@ where return Err(format!("Committee is unknown for epoch {epoch_number}")); } - let (_, committee) = if epoch_number == epoch_of_latest_block.next() { - (self.client.runtime_api()) - .get_next_committee(best_hash) - .map_err(err_debug)? + if epoch_number == epoch_of_latest_block.next() { + self.get_next_committee_versioned(best_hash)? .ok_or(format!("Committee is unknown for the next epoch: {epoch_number}")) } else { let block_hash = self .client .find_block(AnyBlockInEpoch { epoch: epoch_number }) .map_err(err_debug)?; - (self.client.runtime_api()).get_current_committee(block_hash).map_err(err_debug) - }?; - - Ok(GetCommitteeResponse::new(epoch_number, committee)) + self.get_current_committee_versioned(block_hash) + } } async fn get_registrations( diff --git a/toolkit/primitives/session-validator-management/query/src/tests/mod.rs b/toolkit/primitives/session-validator-management/query/src/tests/mod.rs index 993df9b7f..f747870f4 100644 --- a/toolkit/primitives/session-validator-management/query/src/tests/mod.rs +++ b/toolkit/primitives/session-validator-management/query/src/tests/mod.rs @@ -34,7 +34,7 @@ async fn get_epoch_committee() { sidechain_epoch: 777, committee: expected_initial_committee .into_iter() - .map(|key| CommitteeMember::new(key.as_ref())) + .map(|key| CommitteeMember::new(key.authority_id().as_ref())) .collect() } ) @@ -69,7 +69,7 @@ async fn get_epoch_committee_should_return_initial_committee_for_genesis_and_fir runtime_api_mock::committee_for_epoch(conversion::GENESIS_EPOCH); let expected_initial_committee: Vec = expected_initial_committee .into_iter() - .map(|key| CommitteeMember::new(key.as_ref())) + .map(|key| CommitteeMember::new(key.authority_id().as_ref())) .collect(); let GetCommitteeResponse { @@ -95,7 +95,7 @@ async fn get_epoch_committee_should_work_correctly_for_next_epoch() { let expected_committee: Vec<_> = runtime_api_mock::committee_for_epoch(epoch) .into_iter() - .map(|key| CommitteeMember::new(key.as_ref())) + .map(|key| CommitteeMember::new(key.authority_id().as_ref())) .collect(); assert_eq!( diff --git a/toolkit/primitives/session-validator-management/query/src/tests/runtime_api_mock.rs b/toolkit/primitives/session-validator-management/query/src/tests/runtime_api_mock.rs index f0553ed05..3d7aaf566 100644 --- a/toolkit/primitives/session-validator-management/query/src/tests/runtime_api_mock.rs +++ b/toolkit/primitives/session-validator-management/query/src/tests/runtime_api_mock.rs @@ -16,7 +16,7 @@ pub type Block = sp_runtime::generic::Block< >; type SessionKeys = u64; -#[derive(Encode, Decode)] +#[derive(Encode, Decode, Clone)] pub struct CrossChainPublic([u8; 33]); impl AsRef<[u8]> for CrossChainPublic { fn as_ref(&self) -> &[u8] { @@ -44,16 +44,16 @@ sp_api::mock_impl_runtime_apis! { }) } } - impl SessionValidatorManagementApi for TestRuntimeApi { + impl SessionValidatorManagementApi for TestRuntimeApi { #[advanced] - fn get_current_committee(at: ::Hash) -> Result<(ScEpochNumber, sp_std::vec::Vec), sp_api::ApiError> { + fn get_current_committee(at: ::Hash) -> Result<(ScEpochNumber, sp_std::vec::Vec<(CrossChainPublic, SessionKeys)>), sp_api::ApiError> { self.check_using_same_instance_for_same_block(at.encode())?; let block_number = conversion::block_hash_to_block_number(at.into()); let block_epoch = conversion::get_epoch(block_number); Ok((ScEpochNumber(block_epoch as u64), committee_for_epoch(block_epoch as u64))) } #[advanced] - fn get_next_committee(at: ::Hash) -> Result)>, sp_api::ApiError> { + fn get_next_committee(at: ::Hash) -> Result)>, sp_api::ApiError> { self.check_using_same_instance_for_same_block(at.encode())?; let block_number = conversion::block_hash_to_block_number(at.into()) ; let block_epoch = conversion::get_epoch(block_number) + 1; @@ -91,10 +91,10 @@ sp_api::mock_impl_runtime_apis! { } } -pub(crate) fn committee_for_epoch(epoch: u64) -> Vec { +pub(crate) fn committee_for_epoch(epoch: u64) -> Vec<(CrossChainPublic, SessionKeys)> { if epoch == conversion::GENESIS_EPOCH || epoch == conversion::EPOCH_OF_BLOCK_1 { - vec![CrossChainPublic([0u8; 33]), CrossChainPublic([1u8; 33])] + vec![(CrossChainPublic([0u8; 33]), 0), (CrossChainPublic([1u8; 33]), 1)] } else { - vec![CrossChainPublic([epoch as u8; 33]), CrossChainPublic([epoch as u8 + 1; 33])] + vec![(CrossChainPublic([epoch as u8; 33]), 2), (CrossChainPublic([epoch as u8 + 1; 33]), 3)] } } diff --git a/toolkit/primitives/session-validator-management/query/src/types/mod.rs b/toolkit/primitives/session-validator-management/query/src/types/mod.rs index ec0f99357..8fbc14f00 100644 --- a/toolkit/primitives/session-validator-management/query/src/types/mod.rs +++ b/toolkit/primitives/session-validator-management/query/src/types/mod.rs @@ -7,6 +7,7 @@ pub use registrations::*; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_core::bytes::to_hex; +use sp_session_validator_management::CommitteeMember as CommitteeMemberT; #[derive( Clone, Eq, PartialEq, Encode, Decode, Default, TypeInfo, Debug, Serialize, Deserialize, @@ -18,12 +19,28 @@ pub struct GetCommitteeResponse { } impl GetCommitteeResponse { - pub fn new>( + pub fn new( sidechain_epoch: sidechain_domain::ScEpochNumber, - committee: Vec, - ) -> GetCommitteeResponse { - let committee: Vec = - committee.into_iter().map(CommitteeMember::new).collect(); + committee: Vec, + ) -> GetCommitteeResponse + where + Member::AuthorityId: AsRef<[u8]>, + { + let committee = committee + .into_iter() + .map(|member| CommitteeMember::new(member.authority_id())) + .collect(); + GetCommitteeResponse { sidechain_epoch: sidechain_epoch.0, committee } + } + + pub fn new_legacy( + sidechain_epoch: sidechain_domain::ScEpochNumber, + committee: Vec, + ) -> GetCommitteeResponse + where + AuthorityId: AsRef<[u8]>, + { + let committee = committee.into_iter().map(|member| CommitteeMember::new(member)).collect(); GetCommitteeResponse { sidechain_epoch: sidechain_epoch.0, committee } } } @@ -53,7 +70,7 @@ mod tests { fn get_committee_response_to_json_test() { let input = GetCommitteeResponse::new( ScEpochNumber(4703884), - vec![ecdsa::Public::from([0u8; 33]), ecdsa::Public::from([255u8; 33])], + vec![(ecdsa::Public::from([0u8; 33]), 0), (ecdsa::Public::from([255u8; 33]), 1)], ); let json_value = serde_json::to_value(input).expect("Serialization failed"); diff --git a/toolkit/primitives/session-validator-management/src/lib.rs b/toolkit/primitives/session-validator-management/src/lib.rs index 439653e7c..efc2ce1f5 100644 --- a/toolkit/primitives/session-validator-management/src/lib.rs +++ b/toolkit/primitives/session-validator-management/src/lib.rs @@ -107,19 +107,35 @@ impl MainChainScripts { } sp_api::decl_runtime_apis! { + #[api_version(2)] pub trait SessionValidatorManagementApi< - SessionKeys: parity_scale_codec::Decode, - CrossChainPublic: parity_scale_codec::Decode + parity_scale_codec::Encode, + CommitteeMember: parity_scale_codec::Decode + parity_scale_codec::Encode + crate::CommitteeMember, AuthoritySelectionInputs: parity_scale_codec::Encode, ScEpochNumber: parity_scale_codec::Encode + parity_scale_codec::Decode - > { + > where + CommitteeMember::AuthorityId: Encode + Decode, + CommitteeMember::AuthorityKeys: Encode + Decode, + { fn get_main_chain_scripts() -> MainChainScripts; - fn get_current_committee() -> (ScEpochNumber, sp_std::vec::Vec); - fn get_next_committee() -> Option<(ScEpochNumber, sp_std::vec::Vec)>; fn get_next_unset_epoch_number() -> ScEpochNumber; + + #[changed_in(2)] + fn get_current_committee() -> (ScEpochNumber, sp_std::vec::Vec); + fn get_current_committee() -> (ScEpochNumber, sp_std::vec::Vec); + + #[changed_in(2)] + fn get_next_committee() -> Option<(ScEpochNumber, sp_std::vec::Vec)>; + fn get_next_committee() -> Option<(ScEpochNumber, sp_std::vec::Vec)>; + + #[changed_in(2)] + fn calculate_committee( + authority_selection_inputs: AuthoritySelectionInputs, + sidechain_epoch: ScEpochNumber + ) -> Option>; + fn calculate_committee( authority_selection_inputs: AuthoritySelectionInputs, sidechain_epoch: ScEpochNumber - ) -> Option>; + ) -> Option>; } }