mithril_common/messages/message_parts/
signer.rs

1#[cfg(any(test, feature = "test_tools"))]
2use crate::test_utils::fake_keys;
3use crate::{
4    crypto_helper::{KESPeriod, ProtocolOpCert, ProtocolSignerVerificationKeySignature},
5    entities::{
6        HexEncodedOpCert, HexEncodedVerificationKey, HexEncodedVerificationKeySignature, PartyId,
7        Signer, SignerWithStake, Stake,
8    },
9    StdError, StdResult,
10};
11use anyhow::Context;
12use serde::{Deserialize, Serialize};
13use std::fmt::{Debug, Formatter};
14
15/// Signer with Stake Message
16#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
17pub struct SignerWithStakeMessagePart {
18    /// The unique identifier of the signer
19    ///
20    /// Used only for testing when SPO pool id is not certified
21    pub party_id: PartyId,
22
23    /// The public key used to authenticate signer signature
24    pub verification_key: HexEncodedVerificationKey,
25
26    /// The encoded signer 'Mithril verification key' signature (signed by the
27    /// Cardano node KES secret key).
28    ///
29    /// None is used only for testing when SPO pool id is not certified
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub verification_key_signature: Option<HexEncodedVerificationKeySignature>,
32
33    /// The encoded operational certificate of stake pool operator attached to
34    /// the signer node.
35    ///
36    /// None is used only for testing when SPO pool id is not certified
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub operational_certificate: Option<HexEncodedOpCert>,
39
40    /// The KES period used to compute the verification key signature
41    // TODO: This KES period should not be used as is and should probably be
42    //       within an allowed range of KES periods for the epoch.
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub kes_period: Option<KESPeriod>,
45
46    /// The signer stake
47    pub stake: Stake,
48}
49
50impl SignerWithStakeMessagePart {
51    cfg_test_tools! {
52        /// Return a dummy test entity (test-only).
53        pub fn dummy() -> Self {
54            Self {
55                party_id: "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx".to_string(),
56                verification_key: fake_keys::signer_verification_key()[0].to_string(),
57                verification_key_signature: Some(
58                    fake_keys::signer_verification_key_signature()[0].to_string(),
59                ),
60                operational_certificate: Some(fake_keys::operational_certificate()[0].to_string()),
61                kes_period: Some(6),
62                stake: 234,
63            }
64        }
65    }
66
67    /// Convert a set of signers into message parts
68    pub fn from_signers(signers: Vec<SignerWithStake>) -> Vec<Self> {
69        signers.into_iter().map(|signer| signer.into()).collect()
70    }
71
72    /// Convert a set of signer message parts into a set of signers with stake
73    pub fn try_into_signers(messages: Vec<Self>) -> StdResult<Vec<SignerWithStake>> {
74        messages
75            .into_iter()
76            .map(SignerWithStakeMessagePart::try_into)
77            .collect()
78    }
79}
80
81impl TryInto<SignerWithStake> for SignerWithStakeMessagePart {
82    type Error = StdError;
83
84    fn try_into(self) -> Result<SignerWithStake, Self::Error> {
85        let verification_key_signature: Option<ProtocolSignerVerificationKeySignature> = self
86            .verification_key_signature
87            .map(|f| f.try_into())
88            .transpose()
89            .with_context(|| {
90                format!(
91                    "Error while parsing verification key signature message, party_id = '{}'",
92                    self.party_id
93                )
94            })?;
95        let operational_certificate: Option<ProtocolOpCert> = self
96            .operational_certificate
97            .map(|f| f.try_into())
98            .transpose()
99            .with_context(|| {
100                format!(
101                    "Error while parsing operational certificate message, party_id = '{}'.",
102                    self.party_id
103                )
104            })?;
105        let value = SignerWithStake {
106            party_id: self.party_id,
107            verification_key: self.verification_key.try_into()?,
108            verification_key_signature,
109            kes_period: self.kes_period,
110            operational_certificate,
111            stake: self.stake,
112        };
113        Ok(value)
114    }
115}
116
117impl From<SignerWithStake> for SignerWithStakeMessagePart {
118    fn from(value: SignerWithStake) -> Self {
119        Self {
120            party_id: value.party_id,
121            verification_key: value.verification_key.try_into().unwrap(),
122            verification_key_signature: value
123                .verification_key_signature
124                .map(|k| k.try_into().unwrap()),
125            operational_certificate: value
126                .operational_certificate
127                .map(|op_cert| (op_cert.try_into().unwrap())),
128            kes_period: value.kes_period,
129            stake: value.stake,
130        }
131    }
132}
133
134impl Debug for SignerMessagePart {
135    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
136        let should_be_exhaustive = f.alternate();
137        let mut debug = f.debug_struct("Signer");
138        debug.field("party_id", &self.party_id);
139
140        match should_be_exhaustive {
141            true => debug
142                .field(
143                    "verification_key",
144                    &format_args!("{:?}", self.verification_key),
145                )
146                .field(
147                    "verification_key_signature",
148                    &format_args!("{:?}", self.verification_key_signature),
149                )
150                .field(
151                    "operational_certificate",
152                    &format_args!("{:?}", self.operational_certificate),
153                )
154                .field("kes_period", &format_args!("{:?}", self.kes_period))
155                .finish(),
156            false => debug.finish_non_exhaustive(),
157        }
158    }
159}
160
161/// Signer Message
162#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
163pub struct SignerMessagePart {
164    /// The unique identifier of the signer
165    ///
166    /// Used only for testing when SPO pool id is not certified
167    pub party_id: PartyId,
168
169    /// The public key used to authenticate signer signature
170    pub verification_key: HexEncodedVerificationKey,
171
172    /// The encoded signer 'Mithril verification key' signature (signed by the
173    /// Cardano node KES secret key).
174    ///
175    /// None is used only for testing when SPO pool id is not certified
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub verification_key_signature: Option<HexEncodedVerificationKeySignature>,
178
179    /// The encoded operational certificate of stake pool operator attached to
180    /// the signer node.
181    ///
182    /// None is used only for testing when SPO pool id is not certified
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub operational_certificate: Option<HexEncodedOpCert>,
185
186    /// The KES period used to compute the verification key signature
187    // TODO: This KES period should not be used as is and should probably be
188    //       within an allowed range of KES periods for the epoch.
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub kes_period: Option<KESPeriod>,
191}
192
193impl SignerMessagePart {
194    /// Convert a set of signer message parts into a set of signers
195    pub fn try_into_signers(messages: Vec<Self>) -> StdResult<Vec<Signer>> {
196        messages
197            .into_iter()
198            .map(SignerMessagePart::try_into)
199            .collect()
200    }
201
202    /// Convert a set of signers into message parts
203    pub fn from_signers(signers: Vec<Signer>) -> Vec<Self> {
204        signers.into_iter().map(|signer| signer.into()).collect()
205    }
206
207    cfg_test_tools! {
208        /// Return a dummy test entity (test-only).
209        pub fn dummy() -> Self {
210            Self {
211                party_id: "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx".to_string(),
212                verification_key: fake_keys::signer_verification_key()[0].to_string(),
213                verification_key_signature: Some(
214                    fake_keys::signer_verification_key_signature()[0].to_string(),
215                ),
216                operational_certificate: Some(fake_keys::operational_certificate()[0].to_string()),
217                kes_period: Some(6),
218            }
219        }
220    }
221}
222
223impl TryInto<Signer> for SignerMessagePart {
224    type Error = StdError;
225
226    fn try_into(self) -> Result<Signer, Self::Error> {
227        let verification_key_signature: Option<ProtocolSignerVerificationKeySignature> = self
228            .verification_key_signature
229            .map(|f| f.try_into())
230            .transpose()
231            .with_context(|| {
232                format!(
233                    "Error while parsing verification key signature message, party_id = '{}'",
234                    self.party_id
235                )
236            })?;
237        let operational_certificate: Option<ProtocolOpCert> = self
238            .operational_certificate
239            .map(|f| f.try_into())
240            .transpose()
241            .with_context(|| {
242                format!(
243                    "Error while parsing operational certificate message, party_id = '{}'.",
244                    self.party_id
245                )
246            })?;
247        let value = Signer {
248            party_id: self.party_id,
249            verification_key: self.verification_key.try_into()?,
250            verification_key_signature,
251            kes_period: self.kes_period,
252            operational_certificate,
253        };
254        Ok(value)
255    }
256}
257
258impl From<Signer> for SignerMessagePart {
259    fn from(value: Signer) -> Self {
260        Self {
261            party_id: value.party_id,
262            verification_key: value.verification_key.try_into().unwrap(),
263            verification_key_signature: value
264                .verification_key_signature
265                .map(|k| k.try_into().unwrap()),
266            operational_certificate: value
267                .operational_certificate
268                .map(|op_cert| (op_cert.try_into().unwrap())),
269            kes_period: value.kes_period,
270        }
271    }
272}
273
274impl Debug for SignerWithStakeMessagePart {
275    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
276        let should_be_exhaustive = f.alternate();
277        let mut debug = f.debug_struct("Signer");
278        debug
279            .field("party_id", &self.party_id)
280            .field("stake", &self.stake);
281
282        match should_be_exhaustive {
283            true => debug
284                .field(
285                    "verification_key",
286                    &format_args!("{:?}", self.verification_key),
287                )
288                .field(
289                    "verification_key_signature",
290                    &format_args!("{:?}", self.verification_key_signature),
291                )
292                .field(
293                    "operational_certificate",
294                    &format_args!("{:?}", self.operational_certificate),
295                )
296                .field("kes_period", &format_args!("{:?}", self.kes_period))
297                .finish(),
298            false => debug.finish_non_exhaustive(),
299        }
300    }
301}