dubp_documents/membership/
v10.rs1use crate::*;
19
20#[derive(Debug, Deserialize, Clone, Copy, Hash, Serialize, PartialEq, Eq)]
22pub enum MembershipType {
23 In(),
25 Out(),
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
33pub struct MembershipDocumentV10 {
34 text: Option<String>,
38
39 currency: String,
41 issuer: ed25519::PublicKey,
43 blockstamp: Blockstamp,
45 membership: MembershipType,
47 identity_username: String,
49 identity_blockstamp: Blockstamp,
51 signature: ed25519::Signature,
53}
54
55#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
56pub struct MembershipDocumentV10Stringified {
58 pub currency: String,
60 pub issuer: String,
62 pub blockstamp: String,
64 pub membership: String,
66 pub username: String,
68 pub identity_blockstamp: String,
70 pub signature: String,
72}
73
74impl ToStringObject for MembershipDocumentV10 {
75 type StringObject = MembershipDocumentV10Stringified;
76 fn to_string_object(&self) -> MembershipDocumentV10Stringified {
78 MembershipDocumentV10Stringified {
79 currency: self.currency.clone(),
80 issuer: self.issuer.to_base58(),
81 blockstamp: format!("{}", self.blockstamp),
82 membership: match self.membership {
83 MembershipType::In() => "IN".to_owned(),
84 MembershipType::Out() => "OUT".to_owned(),
85 },
86 username: self.identity_username.clone(),
87 identity_blockstamp: format!("{}", self.identity_blockstamp),
88 signature: self.signature.to_base64(),
89 }
90 }
91}
92
93#[derive(Debug, Copy, Clone, PartialEq, Hash, Deserialize, Serialize)]
94pub enum MembershipEventType {
96 Join(),
98 Renewal(),
100 Rejoin(),
102 Expire(),
104}
105
106#[derive(Debug, Clone, PartialEq, Hash, Deserialize, Serialize)]
107pub struct MembershipEvent {
109 pub blockstamp: Blockstamp,
111 pub doc: MembershipDocumentV10,
113 pub event_type: MembershipEventType,
115 pub chainable_on: u64,
117}
118
119impl MembershipDocumentV10 {
120 pub fn membership(&self) -> MembershipType {
122 self.membership
123 }
124
125 pub fn identity_blockstamp(&self) -> Blockstamp {
127 self.identity_blockstamp
128 }
129
130 pub fn identity_username(&self) -> &str {
132 &self.identity_username
133 }
134
135 pub fn reduce(&mut self) {
137 self.text = None;
138 }
139}
140
141impl Document for MembershipDocumentV10 {
142 type PublicKey = ed25519::PublicKey;
143
144 fn version(&self) -> usize {
145 10
146 }
147
148 fn currency(&self) -> &str {
149 &self.currency
150 }
151
152 fn blockstamp(&self) -> Blockstamp {
153 self.blockstamp
154 }
155
156 fn issuers(&self) -> SmallVec<[Self::PublicKey; 1]> {
157 svec![self.issuer]
158 }
159
160 fn signatures(&self) -> SmallVec<[<Self::PublicKey as PublicKey>::Signature; 1]> {
161 svec![self.signature]
162 }
163
164 fn as_bytes(&self) -> BeefCow<[u8]> {
165 BeefCow::borrowed(self.as_text().as_bytes())
166 }
167}
168
169impl CompactTextDocument for MembershipDocumentV10 {
170 fn as_compact_text(&self) -> String {
171 format!(
172 "{issuer}:{signature}:{blockstamp}:{idty_blockstamp}:{username}",
173 issuer = self.issuer,
174 signature = self.signature,
175 blockstamp = self.blockstamp,
176 idty_blockstamp = self.identity_blockstamp,
177 username = self.identity_username,
178 )
179 }
180}
181
182#[derive(Copy, Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
184pub struct CompactPoolMembershipDoc {
185 pub blockstamp: Blockstamp,
187 pub signature: Sig,
189}
190
191impl TextDocument for MembershipDocumentV10 {
192 type CompactTextDocument_ = MembershipDocumentV10;
193
194 fn as_text(&self) -> &str {
195 if let Some(ref text) = self.text {
196 text
197 } else {
198 panic!("Try to get text of reduce membership !")
199 }
200 }
201
202 fn to_compact_document(&self) -> Cow<Self::CompactTextDocument_> {
203 Cow::Borrowed(self)
204 }
205}
206
207#[derive(Debug, Copy, Clone)]
209pub struct MembershipDocumentV10Builder<'a> {
210 pub currency: &'a str,
212 pub issuer: ed25519::PublicKey,
214 pub blockstamp: Blockstamp,
216 pub membership: MembershipType,
218 pub identity_username: &'a str,
220 pub identity_blockstamp: Blockstamp,
222}
223
224impl<'a> TextDocumentBuilder for MembershipDocumentV10Builder<'a> {
225 type Document = MembershipDocumentV10;
226 type Signator = ed25519::Signator;
227
228 fn build_with_text_and_sigs(
229 self,
230 text: String,
231 signatures: SmallVec<
232 [<<Self::Document as Document>::PublicKey as PublicKey>::Signature; 1],
233 >,
234 ) -> MembershipDocumentV10 {
235 MembershipDocumentV10 {
236 text: Some(text),
237 currency: self.currency.to_string(),
238 issuer: self.issuer,
239 blockstamp: self.blockstamp,
240 membership: self.membership,
241 identity_username: self.identity_username.to_string(),
242 identity_blockstamp: self.identity_blockstamp,
243 signature: signatures[0],
244 }
245 }
246
247 fn generate_text(&self) -> String {
248 format!(
249 "Version: 10
250Type: Membership
251Currency: {currency}
252Issuer: {issuer}
253Block: {blockstamp}
254Membership: {membership}
255UserID: {username}
256CertTS: {ity_blockstamp}
257",
258 currency = self.currency,
259 issuer = self.issuer,
260 blockstamp = self.blockstamp,
261 membership = match self.membership {
262 MembershipType::In() => "IN",
263 MembershipType::Out() => "OUT",
264 },
265 username = self.identity_username,
266 ity_blockstamp = self.identity_blockstamp,
267 )
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274 use smallvec::smallvec;
275 use std::str::FromStr;
276 use unwrap::unwrap;
277
278 #[test]
279 fn generate_real_document() {
280 let keypair = ed25519::KeyPairFromSeed32Generator::generate(unwrap!(
281 Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV"),
282 "fail to build Seed32"
283 ));
284 let pubkey = keypair.public_key();
285 let signator = keypair.generate_signator();
286
287 let sig = unwrap!(ed25519::Signature::from_base64(
288 "cUgoc8AI+Tae/AZmRfTnW+xq3XFtmYoUi2LXlmXr8/7LaXiUccQb8+Ds1nZoBp/8+t031HMwqAUpVIqww2FGCg==",
289 ), "fail to build Signature");
290
291 let blockstamp = unwrap!(
292 Blockstamp::from_str(
293 "0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
294 ),
295 "fail to build Blockstamp"
296 );
297
298 let builder = MembershipDocumentV10Builder {
299 currency: "duniter_unit_test_currency",
300 issuer: pubkey,
301 blockstamp,
302 membership: MembershipType::In(),
303 identity_username: "tic",
304 identity_blockstamp: blockstamp,
305 };
306
307 assert!(builder
308 .build_with_signature(smallvec![sig])
309 .verify_signatures()
310 .is_ok());
311 assert!(builder
312 .build_and_sign(vec![signator])
313 .verify_signatures()
314 .is_ok());
315 }
316}