sp_session_validator_management_query/
commands.rs

1//! Implementations for CLI query commands for getting Ariadne params and registration status
2use crate::SessionValidatorManagementQueryApi;
3use sidechain_domain::{McEpochNumber, StakePoolPublicKey};
4
5/// Returns Ariadne parameters in JSON format that are effective for the given epoch
6/// Arguments:
7///  - query: query api implementing [SessionValidatorManagementQueryApi] trait
8///  - mc_epoch_number: mainchain epoch for which to get Ariadne parameters
9pub async fn cli_get_ariadne_parameters(
10	query: impl SessionValidatorManagementQueryApi,
11	mc_epoch_number: McEpochNumber,
12) -> Result<String, String> {
13	let ariadne_parameters = query
14		.get_ariadne_parameters(mc_epoch_number)
15		.await
16		.map_err(|err| err.to_string())?;
17	let json = serde_json::to_value(ariadne_parameters).map_err(|err| err.to_string())?;
18	serde_json::to_string_pretty(&json).map_err(|err| err.to_string())
19}
20
21/// Returns Registration status in JSON format
22/// Arguments:
23///  - query: query api implementing [SessionValidatorManagementQueryApi] trait
24///  - mc_epoch_number: mainchain epoch for which to get Registration status
25///  - stake_pool_public_key: stake pool pub key for which to get Registration status
26pub async fn cli_get_registration_status(
27	query: impl SessionValidatorManagementQueryApi,
28	mc_epoch_number: McEpochNumber,
29	stake_pool_public_key: StakePoolPublicKey,
30) -> Result<String, String> {
31	let registrations = query
32		.get_registrations(mc_epoch_number, stake_pool_public_key.clone())
33		.await
34		.map_err(|err| err.to_string())?;
35	let registrations_json = serde_json::to_value(registrations).map_err(|err| err.to_string())?;
36	serde_json::to_string_pretty(&registrations_json).map_err(|err| err.to_string())
37}
38
39#[cfg(test)]
40mod tests {
41	use super::*;
42	use crate::{
43		QueryResult,
44		types::{
45			AriadneParameters, CandidateRegistrationEntry, DParameter, GetCommitteeResponse,
46			GetRegistrationsResponseMap, PermissionedCandidateData,
47		},
48	};
49	use async_trait::async_trait;
50	use hex_literal::hex;
51	use serde_json::Value;
52	use sidechain_domain::{
53		McBlockNumber, McSlotNumber, McTxHash, McTxIndexInBlock, SidechainPublicKey,
54		StakePoolPublicKey, UtxoId, UtxoIndex, UtxoInfo, byte_string::ByteString,
55	};
56
57	struct MockSessionValidatorManagementQuery {
58		pub ariadne_parameters: Option<AriadneParameters>,
59		pub expected_registrations: Vec<CandidateRegistrationEntry>,
60	}
61
62	#[async_trait]
63	impl SessionValidatorManagementQueryApi for MockSessionValidatorManagementQuery {
64		fn get_epoch_committee(&self, _: u64) -> QueryResult<GetCommitteeResponse> {
65			unimplemented!()
66		}
67
68		async fn get_registrations(
69			&self,
70			_: McEpochNumber,
71			_: StakePoolPublicKey,
72		) -> QueryResult<Vec<CandidateRegistrationEntry>> {
73			Ok(self.expected_registrations.clone())
74		}
75
76		async fn get_ariadne_parameters(
77			&self,
78			epoch_number: McEpochNumber,
79		) -> QueryResult<AriadneParameters> {
80			if epoch_number.0 == 303 {
81				Ok(self.ariadne_parameters.clone().unwrap())
82			} else {
83				Err("unexpected epoch number".into())
84			}
85		}
86	}
87
88	#[tokio::test]
89	async fn ariadne_parameters_returns_correct_json_string() {
90		let d_parameter =
91			DParameter { num_permissioned_candidates: 1, num_registered_candidates: 2 };
92		let permissioned_candidates = vec![PermissionedCandidateData {
93			sidechain_public_key: SidechainPublicKey(
94				hex!("0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb").to_vec(),
95			),
96			keys: vec![
97				(
98					"aura".to_string(),
99					ByteString::from_hex_unsafe(
100						"90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22",
101					),
102				),
103				(
104					"gran".to_string(),
105					ByteString::from_hex_unsafe(
106						"439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f",
107					),
108				),
109			]
110			.into_iter()
111			.collect(),
112			is_valid: true,
113			invalid_reasons: None,
114		}];
115		let candidate_registrations = GetRegistrationsResponseMap::new();
116		let ariadne_parameters = AriadneParameters {
117			d_parameter,
118			permissioned_candidates: Some(permissioned_candidates),
119			candidate_registrations,
120		};
121
122		let query = MockSessionValidatorManagementQuery {
123			ariadne_parameters: Some(ariadne_parameters),
124			expected_registrations: vec![],
125		};
126
127		let cmd_output = cli_get_ariadne_parameters(query, McEpochNumber(303)).await.unwrap();
128
129		assert_eq!(
130			serde_json::from_str::<Value>(&cmd_output).unwrap(),
131			serde_json::json!({
132				"dParameter": {
133					"numPermissionedCandidates": 1,
134					"numRegisteredCandidates": 2
135				},
136				"candidateRegistrations": {},
137				"permissionedCandidates":[
138					{
139						"sidechainPublicKey": "0x0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb",
140						"keys": {"aura":"0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22", "gran": "0x439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f"},
141						"isValid": true
142					}
143				]
144			})
145		);
146	}
147
148	#[tokio::test]
149	async fn cli_get_registration_status_returns_correct_json_string() {
150		let aura = ByteString::from_hex_unsafe(
151			"90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22",
152		);
153		let grandpa = ByteString::from_hex_unsafe(
154			"439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f",
155		);
156		let response = vec![CandidateRegistrationEntry {
157			sidechain_pub_key: "0x0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb".to_string(),
158			sidechain_account_id: "5EP2cMaCxLzhfD3aFAqqgu3kfXH7GcwweEv6JXZRP6ysRHkQ".to_string(),
159			mainchain_pub_key: "0x7521303029fc73ea2dd6a410c4c3cf570bf294a7e02942e049d50ba117acec22".to_string(),
160			cross_chain_pub_key: "0x0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb".to_string(),
161			keys: vec![("aura".to_string(), aura),("gran".to_string(), grandpa)].into_iter().collect(),
162			sidechain_signature: "0x3da1014f1ba4ece29a82b98e2ee4e707bd062523f558e84857cd97d95c525ebd4762812bc1baaf92117861d41acd8641d474f1b30367f0c1ebcf0d280ec44338".to_string(),
163			mainchain_signature: "0x37a45144a24ddd0ded388b7b39441b4ceb7abd1935d02fe6abf07f14025b663e81b53678b3f6701a7c76af7981246537eeee6a790aac18445bb8494bea38990f".to_string(),
164			cross_chain_signature: "0x3da1014f1ba4ece29a82b98e2ee4e707bd062523f558e84857cd97d95c525ebd4762812bc1baaf92117861d41acd8641d474f1b30367f0c1ebcf0d280ec44338".to_string(),
165			utxo: UtxoInfo {
166				utxo_id: UtxoId {
167					tx_hash: McTxHash(hex!("a40c500e3cd4a374916947bc1ff419d5ed1b3e0bef410ba793c3507703f3d6de")),
168					index: UtxoIndex(0),
169				},
170				epoch_number: McEpochNumber(303),
171				block_number: McBlockNumber(1147672),
172				slot_number: McSlotNumber(26223403),
173				tx_index_within_block: McTxIndexInBlock(0),
174			},
175			stake_delegation: Some(2380000000),
176			is_valid: true,
177			invalid_reasons: None,
178		}];
179
180		let query = MockSessionValidatorManagementQuery {
181			ariadne_parameters: None,
182			expected_registrations: response,
183		};
184
185		let cmd_output = cli_get_registration_status(
186			query,
187			McEpochNumber(303),
188			StakePoolPublicKey(hex!(
189				"7521303029fc73ea2dd6a410c4c3cf570bf294a7e02942e049d50ba117acec22"
190			)),
191		)
192		.await
193		.unwrap();
194
195		assert_eq!(
196			serde_json::from_str::<Value>(&cmd_output).unwrap(),
197			serde_json::json!([{
198				"sidechainPubKey": "0x0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb",
199				"sidechainAccountId": "5EP2cMaCxLzhfD3aFAqqgu3kfXH7GcwweEv6JXZRP6ysRHkQ",
200				"mainchainPubKey": "0x7521303029fc73ea2dd6a410c4c3cf570bf294a7e02942e049d50ba117acec22",
201				"crossChainPubKey": "0x0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb",
202				"keys": {"aura":"0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22", "gran":"0x439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f"},
203				"sidechainSignature": "0x3da1014f1ba4ece29a82b98e2ee4e707bd062523f558e84857cd97d95c525ebd4762812bc1baaf92117861d41acd8641d474f1b30367f0c1ebcf0d280ec44338",
204				"mainchainSignature": "0x37a45144a24ddd0ded388b7b39441b4ceb7abd1935d02fe6abf07f14025b663e81b53678b3f6701a7c76af7981246537eeee6a790aac18445bb8494bea38990f",
205				"crossChainSignature": "0x3da1014f1ba4ece29a82b98e2ee4e707bd062523f558e84857cd97d95c525ebd4762812bc1baaf92117861d41acd8641d474f1b30367f0c1ebcf0d280ec44338",
206				"utxo": {
207					"utxoId": "a40c500e3cd4a374916947bc1ff419d5ed1b3e0bef410ba793c3507703f3d6de#0",
208					"epochNumber": 303,
209					"blockNumber": 1147672,
210					"slotNumber": 26223403,
211					"txIndexWithinBlock": 0,
212				},
213				"stakeDelegation": 2380000000u32,
214				"isValid": true
215			}])
216		);
217	}
218}