mithril_client_cli/commands/tools/
aggregator_discovery.rs1use clap::Parser;
2use cli_table::{Cell, Table, print_stdout};
3
4use mithril_client::{
5 AggregatorDiscoveryType, ClientBuilder, MithrilResult, RequiredAggregatorCapabilities,
6 common::{AggregateSignatureType, MithrilNetwork, SignedEntityTypeDiscriminants},
7};
8
9use crate::CommandContext;
10
11#[derive(Parser, Debug, Clone)]
13pub struct AggregatorDiscoveryCommand {
14 network: MithrilNetwork,
16
17 #[clap(long, default_value_t = 1)]
19 max_entries: usize,
20
21 #[clap(long, value_parser, num_args = 0.., value_delimiter = ',')]
25 signed_entity_types: Vec<SignedEntityTypeDiscriminants>,
26
27 #[clap(long, value_parser, num_args = 0.., value_delimiter = ',')]
31 aggregate_signature_types: Vec<AggregateSignatureType>,
32}
33
34impl AggregatorDiscoveryCommand {
35 pub async fn execute(&self, context: CommandContext) -> MithrilResult<()> {
37 let required_capabilities = self.build_required_capabilities();
38 let client_builder =
39 ClientBuilder::new(AggregatorDiscoveryType::Automatic(self.network.clone()))
40 .with_capabilities(required_capabilities);
41 let aggregator_endpoints = client_builder
42 .discover_aggregator(&self.network)?
43 .take(self.max_entries);
44 let lines = aggregator_endpoints.collect::<Vec<_>>();
45
46 if context.is_json_output_enabled() {
47 println!("{}", serde_json::to_string(&lines)?);
48 } else {
49 let lines = lines
50 .into_iter()
51 .map(|endpoint| {
52 let endpoint_clone = endpoint.clone();
53 let capabilities = endpoint_clone.capabilities();
54 vec![
55 endpoint.cell(),
56 capabilities.aggregate_signature_type.cell(),
57 capabilities
58 .signed_entity_types
59 .iter()
60 .map(|signed_entity_type| signed_entity_type.to_string())
61 .collect::<Vec<_>>()
62 .join(",")
63 .cell(),
64 ]
65 })
66 .collect::<Vec<_>>()
67 .table()
68 .title(vec![
69 "Aggregator Endpoint".cell(),
70 "Aggregate Signature Type".cell(),
71 "Signed Entity Types".cell(),
72 ]);
73 print_stdout(lines)?;
74 }
75
76 Ok(())
77 }
78
79 fn build_required_capabilities(&self) -> RequiredAggregatorCapabilities {
80 if self.signed_entity_types.is_empty() && self.aggregate_signature_types.is_empty() {
81 return RequiredAggregatorCapabilities::All;
82 }
83
84 let mut required_capabilities = vec![];
85 if !self.signed_entity_types.is_empty() {
86 let mut required_capabilities_signed_entity_types = vec![];
87 for signed_entity_type in &self.signed_entity_types {
88 required_capabilities_signed_entity_types.push(
89 RequiredAggregatorCapabilities::SignedEntityType(*signed_entity_type),
90 );
91 }
92 required_capabilities.push(RequiredAggregatorCapabilities::And(
93 required_capabilities_signed_entity_types,
94 ));
95 }
96
97 if !self.aggregate_signature_types.is_empty() {
98 let mut required_capabilities_aggregate_signature_types = vec![];
99 for aggregate_signature_type in &self.aggregate_signature_types {
100 required_capabilities_aggregate_signature_types.push(
101 RequiredAggregatorCapabilities::AggregateSignatureType(
102 *aggregate_signature_type,
103 ),
104 );
105 }
106 required_capabilities.push(RequiredAggregatorCapabilities::And(
107 required_capabilities_aggregate_signature_types,
108 ));
109 }
110 if required_capabilities.len() == 1 {
111 required_capabilities.into_iter().next().unwrap()
112 } else {
113 RequiredAggregatorCapabilities::And(required_capabilities)
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use mithril_client::common::SignedEntityTypeDiscriminants;
122
123 #[test]
124 fn test_build_required_capabilities_all() {
125 let command = AggregatorDiscoveryCommand {
126 network: MithrilNetwork::dummy(),
127 max_entries: 1,
128 signed_entity_types: vec![],
129 aggregate_signature_types: vec![],
130 };
131
132 let required_capabilities = command.build_required_capabilities();
133 assert_eq!(required_capabilities, RequiredAggregatorCapabilities::All);
134 }
135
136 #[test]
137 fn test_build_required_capabilities_signed_entity_types() {
138 let command = AggregatorDiscoveryCommand {
139 network: MithrilNetwork::dummy(),
140 max_entries: 1,
141 signed_entity_types: vec![
142 SignedEntityTypeDiscriminants::CardanoTransactions,
143 SignedEntityTypeDiscriminants::CardanoStakeDistribution,
144 ],
145 aggregate_signature_types: vec![],
146 };
147
148 let required_capabilities = command.build_required_capabilities();
149
150 assert_eq!(
151 required_capabilities,
152 RequiredAggregatorCapabilities::And(vec![
153 RequiredAggregatorCapabilities::SignedEntityType(
154 SignedEntityTypeDiscriminants::CardanoTransactions
155 ),
156 RequiredAggregatorCapabilities::SignedEntityType(
157 SignedEntityTypeDiscriminants::CardanoStakeDistribution
158 ),
159 ])
160 );
161 }
162
163 #[test]
164 fn test_build_required_capabilities_aggregate_signature_types() {
165 let command = AggregatorDiscoveryCommand {
166 network: MithrilNetwork::dummy(),
167 max_entries: 1,
168 signed_entity_types: vec![],
169 aggregate_signature_types: vec![AggregateSignatureType::Concatenation],
170 };
171 let required_capabilities = command.build_required_capabilities();
172
173 assert_eq!(
174 required_capabilities,
175 RequiredAggregatorCapabilities::And(vec![
176 RequiredAggregatorCapabilities::AggregateSignatureType(
177 AggregateSignatureType::Concatenation
178 ),
179 ])
180 );
181 }
182
183 #[test]
184 fn test_build_required_capabilities_both() {
185 let command = AggregatorDiscoveryCommand {
186 network: MithrilNetwork::dummy(),
187 max_entries: 1,
188 signed_entity_types: vec![
189 SignedEntityTypeDiscriminants::CardanoTransactions,
190 SignedEntityTypeDiscriminants::CardanoStakeDistribution,
191 ],
192 aggregate_signature_types: vec![AggregateSignatureType::Concatenation],
193 };
194 let required_capabilities = command.build_required_capabilities();
195
196 assert_eq!(
197 required_capabilities,
198 RequiredAggregatorCapabilities::And(vec![
199 RequiredAggregatorCapabilities::And(vec![
200 RequiredAggregatorCapabilities::SignedEntityType(
201 SignedEntityTypeDiscriminants::CardanoTransactions
202 ),
203 RequiredAggregatorCapabilities::SignedEntityType(
204 SignedEntityTypeDiscriminants::CardanoStakeDistribution
205 ),
206 ]),
207 RequiredAggregatorCapabilities::And(vec![
208 RequiredAggregatorCapabilities::AggregateSignatureType(
209 AggregateSignatureType::Concatenation
210 ),
211 ]),
212 ])
213 );
214 }
215}