mithril_common/test/double/
dummies.rs

1use chrono::{DateTime, Utc};
2
3use crate::test::double::{Dummy, fake_data, fake_keys};
4
5mod entities {
6    use crate::crypto_helper::MKTreeStoreInMemory;
7    use crate::entities::*;
8    use crate::test::entities_extensions::CardanoTransactionsSetProofTestExtension;
9
10    use super::*;
11
12    impl Dummy for ChainPoint {
13        /// Return a dummy [ChainPoint] (test-only).
14        fn dummy() -> Self {
15            Self {
16                slot_number: SlotNumber(100),
17                block_number: BlockNumber(0),
18                block_hash: "block_hash-50".to_string(),
19            }
20        }
21    }
22
23    impl Dummy for CardanoTransactionsSetProof {
24        /// Return a dummy [CardanoTransactionsSetProof] (test-only).
25        fn dummy() -> Self {
26            let leaves = vec![
27                (BlockNumber(0), "tx-1".to_string()),
28                (BlockNumber(1), "tx-2".to_string()),
29                (BlockNumber(1), "tx-3".to_string()),
30                (BlockNumber(10), "tx-4".to_string()),
31                (BlockNumber(20), "tx-5".to_string()),
32                (BlockNumber(22), "tx-6".to_string()),
33            ];
34
35            Self::from_leaves::<MKTreeStoreInMemory>(&leaves).unwrap()
36        }
37    }
38
39    impl Dummy for SignedEntityConfig {
40        /// Return a dummy [SignedEntityConfig] (test-only).
41        fn dummy() -> Self {
42            Self {
43                allowed_discriminants: SignedEntityTypeDiscriminants::all(),
44                cardano_transactions_signing_config: CardanoTransactionsSigningConfig::dummy(),
45            }
46        }
47    }
48
49    impl Dummy for CardanoTransactionsSigningConfig {
50        /// Return a dummy [CardanoTransactionsSigningConfig] (test-only).
51        fn dummy() -> Self {
52            Self {
53                security_parameter: BlockNumber(0),
54                step: BlockNumber(15),
55            }
56        }
57    }
58
59    impl Dummy for SignedEntityType {
60        /// Return a dummy [SignedEntityType] (test-only).
61        fn dummy() -> Self {
62            Self::MithrilStakeDistribution(Epoch(5))
63        }
64    }
65
66    impl Dummy for SupportedEra {
67        /// Return a dummy [SupportedEra] (test-only).
68        fn dummy() -> Self {
69            Self::eras().first().unwrap().to_owned()
70        }
71    }
72
73    impl Dummy for TimePoint {
74        /// Return a dummy [TimePoint] (test-only).
75        fn dummy() -> Self {
76            Self::new(10, 100, ChainPoint::dummy())
77        }
78    }
79}
80
81mod messages {
82    use chrono::Duration;
83    use std::collections::BTreeSet;
84
85    use crate::entities::{
86        AncillaryLocation, BlockNumber, CardanoDbBeacon, CardanoTransactionsSetProof,
87        CardanoTransactionsSigningConfig, CompressionAlgorithm, DigestLocation, Epoch,
88        ImmutablesLocation, MultiFilesUri, ProtocolMessage, ProtocolMessagePartKey,
89        ProtocolParameters, SignedEntityType, SignedEntityTypeDiscriminants, StakeDistribution,
90        StakeDistributionParty, TemplateUri,
91    };
92    use crate::messages::*;
93
94    use super::*;
95
96    impl Dummy for CardanoTransactionsSetProofMessagePart {
97        /// Return a dummy [CardanoTransactionsSetProofMessagePart] (test-only).
98        fn dummy() -> Self {
99            CardanoTransactionsSetProof::dummy().try_into().unwrap()
100        }
101    }
102
103    impl Dummy for CertificateMetadataMessagePart {
104        /// Return a dummy [CertificateMetadataMessagePart] (test-only).
105        fn dummy() -> Self {
106            let initiated_at = DateTime::parse_from_rfc3339("2024-02-12T13:11:47Z")
107                .unwrap()
108                .with_timezone(&Utc);
109
110            Self {
111                network: "testnet".to_string(),
112                protocol_version: "0.1.0".to_string(),
113                protocol_parameters: ProtocolParameters::new(1000, 100, 0.123),
114                initiated_at,
115                sealed_at: initiated_at + Duration::try_seconds(100).unwrap(),
116                signers: vec![
117                    StakeDistributionParty {
118                        party_id: "1".to_string(),
119                        stake: 10,
120                    },
121                    StakeDistributionParty {
122                        party_id: "2".to_string(),
123                        stake: 20,
124                    },
125                ],
126            }
127        }
128    }
129
130    impl Dummy for SignerWithStakeMessagePart {
131        /// Return a dummy [SignerWithStakeMessagePart] (test-only).
132        fn dummy() -> Self {
133            Self {
134                party_id: "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx".to_string(),
135                verification_key: fake_keys::signer_verification_key()[0].to_string(),
136                verification_key_signature: Some(
137                    fake_keys::signer_verification_key_signature()[0].to_string(),
138                ),
139                operational_certificate: Some(fake_keys::operational_certificate()[0].to_string()),
140                kes_period: Some(6),
141                stake: 234,
142            }
143        }
144    }
145
146    impl Dummy for SignerMessagePart {
147        /// Return a dummy [SignerMessagePart] (test-only).
148        fn dummy() -> Self {
149            Self {
150                party_id: "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx".to_string(),
151                verification_key: fake_keys::signer_verification_key()[0].to_string(),
152                verification_key_signature: Some(
153                    fake_keys::signer_verification_key_signature()[0].to_string(),
154                ),
155                operational_certificate: Some(fake_keys::operational_certificate()[0].to_string()),
156                kes_period: Some(6),
157            }
158        }
159    }
160
161    impl Dummy for AggregatorFeaturesMessage {
162        /// Return a dummy [AggregatorFeaturesMessage] (test-only).
163        fn dummy() -> Self {
164            AggregatorFeaturesMessage {
165                open_api_version: "0.0.1".to_string(),
166                documentation_url: "https://example.com".to_string(),
167                capabilities: AggregatorCapabilities {
168                    signed_entity_types: BTreeSet::from([
169                        SignedEntityTypeDiscriminants::MithrilStakeDistribution,
170                    ]),
171                    cardano_transactions_prover: None,
172                },
173            }
174        }
175    }
176
177    impl Dummy for CardanoDatabaseSnapshotMessage {
178        /// Return a dummy [CardanoDatabaseSnapshotMessage] (test-only).
179        fn dummy() -> Self {
180            Self {
181                hash: "d4071d518a3ace0f6c04a9c0745b9e9560e3e2af1b373bafc4e0398423e9abfb"
182                    .to_string(),
183                merkle_root: "c8224920b9f5ad7377594eb8a15f34f08eb3103cc5241d57cafc5638403ec7c6"
184                    .to_string(),
185                network: "preview".to_string(),
186                beacon: CardanoDbBeacon {
187                    epoch: Epoch(123),
188                    immutable_file_number: 2345,
189                },
190                certificate_hash:
191                    "f6c01b373bafc4e039844071d5da3ace4a9c0745b9e9560e3e2af01823e9abfb".to_string(),
192                total_db_size_uncompressed: 800796318,
193                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
194                    .unwrap()
195                    .with_timezone(&Utc),
196                digests: DigestsMessagePart {
197                    size_uncompressed: 1024,
198                    locations: vec![DigestLocation::Aggregator {
199                        uri: "https://host-1/digest-1".to_string(),
200                    }],
201                },
202                immutables: ImmutablesMessagePart {
203                    average_size_uncompressed: 512,
204                    locations: vec![
205                        ImmutablesLocation::CloudStorage {
206                            uri: MultiFilesUri::Template(TemplateUri(
207                                "https://host-1/immutables-2".to_string(),
208                            )),
209                            compression_algorithm: Some(CompressionAlgorithm::Gzip),
210                        },
211                        ImmutablesLocation::CloudStorage {
212                            uri: MultiFilesUri::Template(TemplateUri(
213                                "https://host-2/immutables-2".to_string(),
214                            )),
215                            compression_algorithm: Some(CompressionAlgorithm::Gzip),
216                        },
217                    ],
218                },
219                ancillary: AncillaryMessagePart {
220                    size_uncompressed: 2048,
221                    locations: vec![AncillaryLocation::CloudStorage {
222                        uri: "https://host-1/ancillary-3".to_string(),
223                        compression_algorithm: Some(CompressionAlgorithm::Gzip),
224                    }],
225                },
226                cardano_node_version: "0.0.1".to_string(),
227            }
228        }
229    }
230
231    impl Dummy for CardanoDatabaseDigestListItemMessage {
232        /// Return a dummy [CardanoDatabaseDigestListItemMessage] (test-only).
233        fn dummy() -> Self {
234            Self {
235                immutable_file_name: "06685.chunk".to_string(),
236                digest: "0af556ab2620dd9363bf76963a231abe8948a500ea6be31b131d87907ab09b1e"
237                    .to_string(),
238            }
239        }
240    }
241
242    impl Dummy for CardanoDatabaseImmutableFilesRestoredMessage {
243        /// Return a dummy [CardanoDatabaseImmutableFilesRestoredMessage] (test-only).
244        fn dummy() -> Self {
245            Self {
246                nb_immutable_files: 34,
247            }
248        }
249    }
250
251    impl Dummy for CardanoDatabaseSnapshotListItemMessage {
252        /// Return a dummy [CardanoDatabaseSnapshotListItemMessage] (test-only).
253        fn dummy() -> Self {
254            Self {
255                hash: "d4071d518a3ace0f6c04a9c0745b9e9560e3e2af1b373bafc4e0398423e9abfb"
256                    .to_string(),
257                merkle_root: "c8224920b9f5ad7377594eb8a15f34f08eb3103cc5241d57cafc5638403ec7c6"
258                    .to_string(),
259                beacon: CardanoDbBeacon {
260                    epoch: Epoch(123),
261                    immutable_file_number: 2345,
262                },
263                certificate_hash:
264                    "f6c01b373bafc4e039844071d5da3ace4a9c0745b9e9560e3e2af01823e9abfb".to_string(),
265                total_db_size_uncompressed: 800796318,
266                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
267                    .unwrap()
268                    .with_timezone(&Utc),
269                cardano_node_version: "0.0.1".to_string(),
270            }
271        }
272    }
273
274    impl Dummy for CardanoStakeDistributionMessage {
275        /// Return a dummy [CardanoStakeDistributionMessage] (test-only).
276        fn dummy() -> Self {
277            Self {
278                epoch: Epoch(1),
279                hash: "hash-123".to_string(),
280                certificate_hash: "cert-hash-123".to_string(),
281                stake_distribution: StakeDistribution::from([("pool-123".to_string(), 1000)]),
282                created_at: DateTime::parse_from_rfc3339("2024-07-29T16:15:05.618857482Z")
283                    .unwrap()
284                    .with_timezone(&Utc),
285            }
286        }
287    }
288
289    impl Dummy for CardanoStakeDistributionListItemMessage {
290        /// Return a dummy [CardanoStakeDistributionListItemMessage] (test-only).
291        fn dummy() -> Self {
292            Self {
293                epoch: Epoch(1),
294                hash: "hash-123".to_string(),
295                certificate_hash: "certificate-hash-123".to_string(),
296                created_at: DateTime::parse_from_rfc3339("2024-07-29T16:15:05.618857482Z")
297                    .unwrap()
298                    .with_timezone(&Utc),
299            }
300        }
301    }
302
303    impl Dummy for CardanoTransactionSnapshotMessage {
304        /// Return a dummy [CertificateMessage] (test-only).
305        fn dummy() -> Self {
306            Self {
307                merkle_root: "mkroot-123".to_string(),
308                epoch: Epoch(10),
309                block_number: BlockNumber(100),
310                hash: "hash-123".to_string(),
311                certificate_hash: "cert-hash-123".to_string(),
312                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
313                    .unwrap()
314                    .with_timezone(&Utc),
315            }
316        }
317    }
318
319    impl Dummy for CardanoTransactionSnapshotListItemMessage {
320        /// Return a dummy [CertificateMessage] (test-only).
321        fn dummy() -> Self {
322            Self {
323                merkle_root: "mkroot-123".to_string(),
324                epoch: Epoch(10),
325                block_number: BlockNumber(100),
326                hash: "hash-123".to_string(),
327                certificate_hash: "cert-hash-123".to_string(),
328                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
329                    .unwrap()
330                    .with_timezone(&Utc),
331            }
332        }
333    }
334
335    impl Dummy for CertificateMessage {
336        /// Return a dummy [CertificateMessage] (test-only).
337        fn dummy() -> Self {
338            let mut protocol_message = ProtocolMessage::new();
339            protocol_message.set_message_part(
340                ProtocolMessagePartKey::SnapshotDigest,
341                "snapshot-digest-123".to_string(),
342            );
343            protocol_message.set_message_part(
344                ProtocolMessagePartKey::NextAggregateVerificationKey,
345                fake_keys::aggregate_verification_key()[1].to_owned(),
346            );
347            let epoch = Epoch(10);
348
349            Self {
350                hash: "hash".to_string(),
351                previous_hash: "previous_hash".to_string(),
352                epoch,
353                signed_entity_type: SignedEntityType::MithrilStakeDistribution(epoch),
354                metadata: CertificateMetadataMessagePart::dummy(),
355                protocol_message: protocol_message.clone(),
356                signed_message: "signed_message".to_string(),
357                aggregate_verification_key: fake_keys::aggregate_verification_key()[0].to_owned(),
358                multi_signature: fake_keys::multi_signature()[0].to_owned(),
359                genesis_signature: String::new(),
360            }
361        }
362    }
363
364    impl Dummy for CertificateListItemMessage {
365        /// Return a dummy [CertificateListItemMessage] (test-only).
366        fn dummy() -> Self {
367            let mut protocol_message = ProtocolMessage::new();
368            protocol_message.set_message_part(
369                ProtocolMessagePartKey::SnapshotDigest,
370                "snapshot-digest-123".to_string(),
371            );
372            protocol_message.set_message_part(
373                ProtocolMessagePartKey::NextAggregateVerificationKey,
374                "next-avk-123".to_string(),
375            );
376            let epoch = Epoch(10);
377
378            Self {
379                hash: "hash".to_string(),
380                previous_hash: "previous_hash".to_string(),
381                epoch,
382                signed_entity_type: SignedEntityType::MithrilStakeDistribution(epoch),
383                metadata: CertificateListItemMessageMetadata {
384                    network: "testnet".to_string(),
385                    protocol_version: "0.1.0".to_string(),
386                    protocol_parameters: ProtocolParameters::new(1000, 100, 0.123),
387                    initiated_at: DateTime::parse_from_rfc3339("2024-02-12T13:11:47Z")
388                        .unwrap()
389                        .with_timezone(&Utc),
390                    sealed_at: DateTime::parse_from_rfc3339("2024-02-12T13:12:57Z")
391                        .unwrap()
392                        .with_timezone(&Utc),
393                    total_signers: 2,
394                },
395                protocol_message: protocol_message.clone(),
396                signed_message: "signed_message".to_string(),
397                aggregate_verification_key: "aggregate_verification_key".to_string(),
398            }
399        }
400    }
401
402    impl Dummy for EpochSettingsMessage {
403        /// Return a dummy [EpochSettingsMessage] (test-only).
404        fn dummy() -> Self {
405            Self {
406                epoch: Epoch(10),
407                signer_registration_protocol_parameters: ProtocolParameters {
408                    k: 5,
409                    m: 100,
410                    phi_f: 0.65,
411                },
412                current_signers: [SignerMessagePart::dummy()].to_vec(),
413                next_signers: [SignerMessagePart::dummy()].to_vec(),
414                cardano_transactions_signing_config: Some(CardanoTransactionsSigningConfig::dummy()),
415            }
416        }
417    }
418
419    impl Dummy for MithrilStakeDistributionMessage {
420        /// Return a dummy [MithrilStakeDistributionMessage] (test-only).
421        fn dummy() -> Self {
422            Self {
423                epoch: Epoch(1),
424                signers_with_stake: vec![SignerWithStakeMessagePart::dummy()],
425                hash: "hash-123".to_string(),
426                certificate_hash: "cert-hash-123".to_string(),
427                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
428                    .unwrap()
429                    .with_timezone(&Utc),
430                protocol_parameters: fake_data::protocol_parameters(),
431            }
432        }
433    }
434
435    impl Dummy for MithrilStakeDistributionListItemMessage {
436        /// Return a dummy [MithrilStakeDistributionListItemMessage] (test-only).
437        fn dummy() -> Self {
438            Self {
439                epoch: Epoch(1),
440                hash: "hash-123".to_string(),
441                certificate_hash: "certificate-hash-123".to_string(),
442                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
443                    .unwrap()
444                    .with_timezone(&Utc),
445            }
446        }
447    }
448
449    impl Dummy for RegisterSignatureMessageHttp {
450        /// Return a dummy [RegisterSignatureMessageHttp] (test-only).
451        fn dummy() -> Self {
452            use crate::entities::Epoch;
453            Self {
454                signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(5)),
455                party_id: "party_id".to_string(),
456                signature: fake_keys::single_signature()[0].to_string(),
457                won_indexes: vec![1, 3],
458                signed_message: "6a7e737c312972d2346b65ac3075696e04286d046dddaf8004121e3d5e27cc0d"
459                    .to_string(),
460            }
461        }
462    }
463
464    impl Dummy for RegisterSignatureMessageDmq {
465        /// Return a dummy [RegisterSignatureMessageDmq] (test-only).
466        fn dummy() -> Self {
467            use crate::entities::Epoch;
468            Self {
469                signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(5)),
470                signature: fake_keys::single_signature()[0].try_into().unwrap(),
471            }
472        }
473    }
474
475    impl Dummy for RegisterSignerMessage {
476        /// Return a dummy [RegisterSignerMessage] (test-only).
477        fn dummy() -> Self {
478            Self {
479                epoch: Epoch(1),
480                party_id: "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx".to_string(),
481                verification_key: fake_keys::signer_verification_key()[0].to_string(),
482                verification_key_signature: Some(
483                    fake_keys::signer_verification_key_signature()[0].to_string(),
484                ),
485                operational_certificate: Some(fake_keys::operational_certificate()[0].to_string()),
486                kes_period: Some(6),
487            }
488        }
489    }
490
491    impl Dummy for SnapshotMessage {
492        /// Return a dummy [SnapshotMessage] (test-only).
493        fn dummy() -> Self {
494            Self {
495                digest: "0b9f5ad7f33cc523775c82249294eb8a1541d54f08eb3107cafc5638403ec7c6"
496                    .to_string(),
497                network: "preview".to_string(),
498                beacon: CardanoDbBeacon {
499                    epoch: Epoch(86),
500                    immutable_file_number: 1728,
501                },
502                certificate_hash:
503                    "d5daf6c03ace4a9c074e951844075b9b373bafc4e039160e3e2af01823e9abfb".to_string(),
504                size: 807803196,
505                ancillary_size: Some(123456789),
506                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
507                    .unwrap()
508                    .with_timezone(&Utc),
509                locations: vec!["https://host/certificate.tar.gz".to_string()],
510                ancillary_locations: Some(vec!["https://host/ancillary.tar.gz".to_string()]),
511                compression_algorithm: CompressionAlgorithm::Gzip,
512                cardano_node_version: "0.0.1".to_string(),
513            }
514        }
515    }
516
517    impl Dummy for SnapshotDownloadMessage {
518        /// Return a dummy [SnapshotDownloadMessage] (test-only).
519        fn dummy() -> Self {
520            Self {
521                digest: "0b9f5ad7f33cc523775c82249294eb8a1541d54f08eb3107cafc5638403ec7c6"
522                    .to_string(),
523                network: "preview".to_string(),
524                beacon: CardanoDbBeacon {
525                    epoch: Epoch(86),
526                    immutable_file_number: 1728,
527                },
528                size: 807803196,
529                ancillary_size: Some(123456789),
530                locations: vec!["https://host/certificate.tar.gz".to_string()],
531                ancillary_locations: Some(vec!["https://host/ancillary.tar.gz".to_string()]),
532                compression_algorithm: CompressionAlgorithm::Gzip,
533                cardano_node_version: "0.0.1".to_string(),
534            }
535        }
536    }
537
538    impl Dummy for SnapshotListItemMessage {
539        /// Return a dummy [SnapshotListItemMessage] (test-only).
540        fn dummy() -> Self {
541            Self {
542                digest: "0b9f5ad7f33cc523775c82249294eb8a1541d54f08eb3107cafc5638403ec7c6"
543                    .to_string(),
544                network: "preview".to_string(),
545                beacon: CardanoDbBeacon {
546                    epoch: Epoch(86),
547                    immutable_file_number: 1728,
548                },
549                certificate_hash:
550                    "d5daf6c03ace4a9c074e951844075b9b373bafc4e039160e3e2af01823e9abfb".to_string(),
551                size: 807803196,
552                ancillary_size: Some(123456789),
553                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
554                    .unwrap()
555                    .with_timezone(&Utc),
556                locations: vec!["https://host/certificate.tar.gz".to_string()],
557                ancillary_locations: Some(vec!["https://host/ancillary.tar.gz".to_string()]),
558                compression_algorithm: CompressionAlgorithm::default(),
559                cardano_node_version: "0.0.1".to_string(),
560            }
561        }
562    }
563}
564
565mod signable_builder {
566    use crate::entities::{
567        CardanoDbBeacon, CardanoStakeDistribution, CardanoTransactionsSnapshot, Epoch,
568        MithrilStakeDistribution, SignedEntityType, Snapshot,
569    };
570    use crate::signable_builder::SignedEntity;
571
572    use super::*;
573
574    impl Dummy for SignedEntity<Snapshot> {
575        /// Create a dummy [SignedEntity] for [Snapshot] entity
576        fn dummy() -> Self {
577            SignedEntity {
578                signed_entity_id: "snapshot-id-123".to_string(),
579                signed_entity_type: SignedEntityType::CardanoImmutableFilesFull(
580                    CardanoDbBeacon::default(),
581                ),
582                certificate_id: "certificate-hash-123".to_string(),
583                artifact: fake_data::snapshots(1)[0].to_owned(),
584                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
585                    .unwrap()
586                    .with_timezone(&Utc),
587            }
588        }
589    }
590
591    impl Dummy for SignedEntity<MithrilStakeDistribution> {
592        /// Create a dummy [SignedEntity] for [MithrilStakeDistribution] entity
593        fn dummy() -> Self {
594            SignedEntity {
595                signed_entity_id: "mithril-stake-distribution-id-123".to_string(),
596                signed_entity_type: SignedEntityType::MithrilStakeDistribution(Epoch(1)),
597                certificate_id: "certificate-hash-123".to_string(),
598                artifact: fake_data::mithril_stake_distributions(1)[0].to_owned(),
599                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
600                    .unwrap()
601                    .with_timezone(&Utc),
602            }
603        }
604    }
605
606    impl Dummy for SignedEntity<CardanoTransactionsSnapshot> {
607        /// Create a dummy [SignedEntity] for [CardanoTransactionsSnapshot] entity
608        fn dummy() -> Self {
609            let block_number = crate::entities::BlockNumber(50);
610            SignedEntity {
611                signed_entity_id: "snapshot-id-123".to_string(),
612                signed_entity_type: SignedEntityType::CardanoTransactions(Epoch(5), block_number),
613                certificate_id: "certificate-hash-123".to_string(),
614                artifact: CardanoTransactionsSnapshot::new("mkroot123".to_string(), block_number),
615                created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
616                    .unwrap()
617                    .with_timezone(&Utc),
618            }
619        }
620    }
621
622    impl Dummy for SignedEntity<CardanoStakeDistribution> {
623        /// Create a dummy [SignedEntity] for [CardanoStakeDistribution] entity
624        fn dummy() -> Self {
625            SignedEntity {
626                signed_entity_id: "cardano-stake-distribution-id-123".to_string(),
627                signed_entity_type: SignedEntityType::CardanoStakeDistribution(Epoch(1)),
628                certificate_id: "certificate-hash-123".to_string(),
629                artifact: fake_data::cardano_stake_distributions(1)[0].to_owned(),
630                created_at: DateTime::parse_from_rfc3339("2024-07-29T16:15:05.618857482Z")
631                    .unwrap()
632                    .with_timezone(&Utc),
633            }
634        }
635    }
636}