mithril_aggregator/database/record/
signer_registration.rs1use chrono::{DateTime, Utc};
2
3use mithril_common::crypto_helper::KesPeriod;
4use mithril_common::entities::{
5 Epoch, HexEncodedOpCert, HexEncodedVerificationKey, HexEncodedVerificationKeySignature, Signer,
6 SignerWithStake, Stake,
7};
8use mithril_persistence::sqlite::{HydrationError, Projection, SqLiteEntity};
9
10#[derive(Debug, PartialEq, Clone)]
12pub struct SignerRegistrationRecord {
13 pub signer_id: String,
15
16 pub epoch_settings_id: Epoch,
18
19 pub verification_key: HexEncodedVerificationKey,
21
22 pub verification_key_signature: Option<HexEncodedVerificationKeySignature>,
24
25 pub operational_certificate: Option<HexEncodedOpCert>,
27
28 pub kes_period: Option<KesPeriod>,
33
34 pub stake: Option<Stake>,
36
37 pub created_at: DateTime<Utc>,
39}
40
41impl SignerRegistrationRecord {
42 pub(crate) fn from_signer_with_stake(other: SignerWithStake, epoch: Epoch) -> Self {
43 SignerRegistrationRecord {
44 signer_id: other.party_id,
45 epoch_settings_id: epoch,
46 verification_key: other.verification_key.to_json_hex().unwrap(),
47 verification_key_signature: other
48 .verification_key_signature
49 .map(|k| k.to_json_hex().unwrap()),
50 operational_certificate: other
51 .operational_certificate
52 .map(|o| o.to_json_hex().unwrap()),
53 kes_period: other.kes_evolutions,
54 stake: Some(other.stake),
55 created_at: Utc::now(),
56 }
57 }
58}
59
60impl From<SignerRegistrationRecord> for Signer {
61 fn from(other: SignerRegistrationRecord) -> Self {
62 Self {
63 party_id: other.signer_id,
64 verification_key: other.verification_key.try_into().unwrap(),
65 verification_key_signature: other
66 .verification_key_signature
67 .map(|k| k.try_into().unwrap()),
68 operational_certificate: other.operational_certificate.map(|o| o.try_into().unwrap()),
69 kes_evolutions: other.kes_period,
70 }
71 }
72}
73
74impl From<SignerRegistrationRecord> for SignerWithStake {
75 fn from(other: SignerRegistrationRecord) -> Self {
76 Self {
77 party_id: other.signer_id,
78 verification_key: other.verification_key.try_into().unwrap(),
79 verification_key_signature: other
80 .verification_key_signature
81 .map(|k| k.try_into().unwrap()),
82 operational_certificate: other.operational_certificate.map(|o| o.try_into().unwrap()),
83 kes_evolutions: other.kes_period,
84 stake: other.stake.unwrap_or_default(),
85 }
86 }
87}
88
89impl SqLiteEntity for SignerRegistrationRecord {
90 fn hydrate(row: sqlite::Row) -> Result<Self, HydrationError>
91 where
92 Self: Sized,
93 {
94 let signer_id = row.read::<&str, _>(0).to_string();
95 let epoch_settings_id_int = row.read::<i64, _>(1);
96 let verification_key = row.read::<&str, _>(2).to_string();
97 let verification_key_signature = row.read::<Option<&str>, _>(3).map(|s| s.to_owned());
98 let operational_certificate = row.read::<Option<&str>, _>(4).map(|s| s.to_owned());
99 let kes_period_int = row.read::<Option<i64>, _>(5);
100 let stake_int = row.read::<Option<i64>, _>(6);
101 let created_at = row.read::<&str, _>(7);
102
103 let signer_registration_record = Self {
104 signer_id,
105 epoch_settings_id: Epoch(epoch_settings_id_int.try_into().map_err(|e| {
106 HydrationError::InvalidData(format!(
107 "Could not cast i64 ({epoch_settings_id_int}) to u64. Error: '{e}'"
108 ))
109 })?),
110 verification_key,
111 verification_key_signature,
112 operational_certificate,
113 kes_period: match kes_period_int {
114 Some(kes_period_int) => Some(kes_period_int.try_into().map_err(|e| {
115 HydrationError::InvalidData(format!(
116 "Could not cast i64 ({kes_period_int}) to u64. Error: '{e}'"
117 ))
118 })?),
119 None => None,
120 },
121 stake: match stake_int {
122 Some(stake_int) => Some(stake_int.try_into().map_err(|e| {
123 HydrationError::InvalidData(format!(
124 "Could not cast i64 ({stake_int}) to u64. Error: '{e}'"
125 ))
126 })?),
127 None => None,
128 },
129 created_at: DateTime::parse_from_rfc3339(created_at)
130 .map_err(|e| {
131 HydrationError::InvalidData(format!(
132 "Could not turn string '{created_at}' to rfc3339 Datetime. Error: {e}"
133 ))
134 })?
135 .with_timezone(&Utc),
136 };
137
138 Ok(signer_registration_record)
139 }
140
141 fn get_projection() -> Projection {
142 let mut projection = Projection::default();
143 projection.add_field("signer_id", "{:signer_registration:}.signer_id", "text");
144 projection.add_field(
145 "epoch_setting_id",
146 "{:signer_registration:}.epoch_setting_id",
147 "integer",
148 );
149 projection.add_field(
150 "verification_key",
151 "{:signer_registration:}.verification_key",
152 "text",
153 );
154 projection.add_field(
155 "verification_key_signature",
156 "{:signer_registration:}.verification_key_signature",
157 "text",
158 );
159 projection.add_field(
160 "operational_certificate",
161 "{:signer_registration:}.operational_certificate",
162 "text",
163 );
164 projection.add_field(
165 "kes_period",
166 "{:signer_registration:}.kes_period",
167 "integer",
168 );
169 projection.add_field("stake", "{:signer_registration:}.stake", "integer");
170 projection.add_field("created_at", "{:signer_registration:}.created_at", "text");
171
172 projection
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use mithril_common::test::builder::MithrilFixtureBuilder;
179
180 use super::*;
181
182 #[test]
183 fn test_convert_signer_registrations() {
184 let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
185 let signer_with_stakes = fixture.signers_with_stake();
186
187 let mut signer_registration_records: Vec<SignerRegistrationRecord> = Vec::new();
188 for signer_with_stake in signer_with_stakes.clone() {
189 signer_registration_records.push(SignerRegistrationRecord::from_signer_with_stake(
190 signer_with_stake,
191 Epoch(1),
192 ));
193 }
194 let mut signer_with_stakes_new: Vec<SignerWithStake> = Vec::new();
195 for signer_registration_record in signer_registration_records {
196 signer_with_stakes_new.push(signer_registration_record.into());
197 }
198 assert_eq!(signer_with_stakes, signer_with_stakes_new);
199 }
200}