mithril_aggregator/tools/
single_signature_authenticator.rs1use slog::{Logger, debug};
2use std::sync::Arc;
3
4use mithril_common::StdResult;
5use mithril_common::entities::{SingleSignature, SingleSignatureAuthenticationStatus};
6use mithril_common::logging::LoggerExtensions;
7
8use crate::MultiSigner;
9
10pub struct SingleSignatureAuthenticator {
12 multi_signer: Arc<dyn MultiSigner>,
13 logger: Logger,
14}
15
16impl SingleSignatureAuthenticator {
17 pub fn new(multi_signer: Arc<dyn MultiSigner>, logger: Logger) -> Self {
19 Self {
20 multi_signer,
21 logger: logger.new_with_component_name::<Self>(),
22 }
23 }
24
25 pub async fn authenticate(
27 &self,
28 single_signature: &mut SingleSignature,
29 signed_message: &str,
30 ) -> StdResult<()> {
31 let is_authenticated = match self
32 .multi_signer
33 .verify_single_signature(signed_message, single_signature)
34 .await
35 {
36 Ok(()) => {
37 debug!(
38 self.logger, "Single signature party authenticated for current stake distribution";
39 "party_id" => &single_signature.party_id,
40 );
41 true
42 }
43 Err(_error) => {
44 if self
47 .multi_signer
48 .verify_single_signature_for_next_stake_distribution(
49 signed_message,
50 single_signature,
51 )
52 .await
53 .is_ok()
54 {
55 debug!(
56 self.logger, "Single signature party authenticated for next stake distribution";
57 "party_id" => &single_signature.party_id,
58 );
59 true
60 } else {
61 debug!(
62 self.logger, "Single signature party not authenticated";
63 "party_id" => &single_signature.party_id,
64 );
65 false
66 }
67 }
68 };
69
70 single_signature.authentication_status = if is_authenticated {
71 SingleSignatureAuthenticationStatus::Authenticated
72 } else {
73 SingleSignatureAuthenticationStatus::Unauthenticated
74 };
75
76 Ok(())
77 }
78}
79
80#[cfg(test)]
81impl SingleSignatureAuthenticator {
82 pub(crate) fn new_that_authenticate_everything() -> Self {
83 let mut multi_signer = crate::multi_signer::MockMultiSigner::new();
84 multi_signer.expect_verify_single_signature().returning(|_, _| Ok(()));
85 multi_signer
86 .expect_verify_single_signature_for_next_stake_distribution()
87 .returning(|_, _| Ok(()));
88
89 Self {
90 multi_signer: Arc::new(multi_signer),
91 logger: crate::test_tools::TestLogger::stdout(),
92 }
93 }
94
95 pub(crate) fn new_that_reject_everything() -> Self {
96 let mut multi_signer = crate::multi_signer::MockMultiSigner::new();
97 multi_signer
98 .expect_verify_single_signature()
99 .returning(|_, _| Err(anyhow::anyhow!("error")));
100 multi_signer
101 .expect_verify_single_signature_for_next_stake_distribution()
102 .returning(|_, _| Err(anyhow::anyhow!("error")));
103
104 Self {
105 multi_signer: Arc::new(multi_signer),
106 logger: crate::test_tools::TestLogger::stdout(),
107 }
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use anyhow::anyhow;
114
115 use crate::multi_signer::MockMultiSigner;
116 use crate::test_tools::TestLogger;
117
118 use super::*;
119
120 fn mock_multi_signer(
121 multi_signer_mock_config: impl FnOnce(&mut MockMultiSigner),
122 ) -> Arc<MockMultiSigner> {
123 let mut multi_signer = MockMultiSigner::new();
124 multi_signer_mock_config(&mut multi_signer);
125 Arc::new(multi_signer)
126 }
127
128 #[tokio::test]
129 async fn single_signature_against_valid_signed_message_for_current_stake_distribution_is_authenticated()
130 {
131 let signed_message = "signed_message".to_string();
132 let mut single_signature = SingleSignature {
133 authentication_status: SingleSignatureAuthenticationStatus::Unauthenticated,
134 ..SingleSignature::fake("party_id", &signed_message)
135 };
136
137 let authenticator = SingleSignatureAuthenticator::new(
138 mock_multi_signer(|mock_config| {
139 mock_config.expect_verify_single_signature().returning(|_, _| Ok(()));
140 }),
141 TestLogger::stdout(),
142 );
143
144 authenticator
145 .authenticate(&mut single_signature, &signed_message)
146 .await
147 .unwrap();
148
149 assert_eq!(
150 single_signature.authentication_status,
151 SingleSignatureAuthenticationStatus::Authenticated
152 );
153 }
154
155 #[tokio::test]
156 async fn single_signature_against_valid_signed_message_for_next_stake_distribution_is_authenticated()
157 {
158 let signed_message = "signed_message".to_string();
159 let mut single_signature = SingleSignature {
160 authentication_status: SingleSignatureAuthenticationStatus::Unauthenticated,
161 ..SingleSignature::fake("party_id", &signed_message)
162 };
163
164 let authenticator = SingleSignatureAuthenticator::new(
165 mock_multi_signer(|mock_config| {
166 mock_config
167 .expect_verify_single_signature()
168 .returning(|_, _| Err(anyhow!("error")));
169 mock_config
170 .expect_verify_single_signature_for_next_stake_distribution()
171 .returning(|_, _| Ok(()));
172 }),
173 TestLogger::stdout(),
174 );
175
176 authenticator
177 .authenticate(&mut single_signature, &signed_message)
178 .await
179 .unwrap();
180
181 assert_eq!(
182 single_signature.authentication_status,
183 SingleSignatureAuthenticationStatus::Authenticated
184 );
185 }
186
187 #[tokio::test]
188 async fn single_signature_against_invalid_signed_message_for_current_and_next_stake_distribution_is_not_authenticated()
189 {
190 let signed_message = "signed_message".to_string();
191 let mut single_signature = SingleSignature {
192 authentication_status: SingleSignatureAuthenticationStatus::Unauthenticated,
193 ..SingleSignature::fake("party_id", &signed_message)
194 };
195
196 let authenticator = SingleSignatureAuthenticator::new(
197 mock_multi_signer(|mock_config| {
198 mock_config
199 .expect_verify_single_signature()
200 .returning(|_, _| Err(anyhow!("verify_single_signature error")));
201 mock_config
202 .expect_verify_single_signature_for_next_stake_distribution()
203 .returning(|_, _| {
204 Err(anyhow!(
205 "verify_single_signature_for_next_stake_distribution error"
206 ))
207 });
208 }),
209 TestLogger::stdout(),
210 );
211
212 authenticator
213 .authenticate(&mut single_signature, &signed_message)
214 .await
215 .unwrap();
216
217 assert_eq!(
218 single_signature.authentication_status,
219 SingleSignatureAuthenticationStatus::Unauthenticated
220 );
221 }
222
223 #[tokio::test]
224 async fn single_signature_previously_authenticated_but_fail_new_authentication_is_now_unauthenticated()
225 {
226 let signed_message = "signed_message".to_string();
227 let mut single_signature = SingleSignature {
228 authentication_status: SingleSignatureAuthenticationStatus::Authenticated,
229 ..SingleSignature::fake("party_id", &signed_message)
230 };
231
232 let authenticator = SingleSignatureAuthenticator::new(
233 mock_multi_signer(|mock_config| {
234 mock_config
235 .expect_verify_single_signature()
236 .returning(|_, _| Err(anyhow!("verify_single_signature error")));
237 mock_config
238 .expect_verify_single_signature_for_next_stake_distribution()
239 .returning(|_, _| {
240 Err(anyhow!(
241 "verify_single_signature_for_next_stake_distribution error"
242 ))
243 });
244 }),
245 TestLogger::stdout(),
246 );
247
248 authenticator
249 .authenticate(&mut single_signature, &signed_message)
250 .await
251 .unwrap();
252
253 assert_eq!(
254 single_signature.authentication_status,
255 SingleSignatureAuthenticationStatus::Unauthenticated
256 );
257 }
258}