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