mithril_aggregator/services/certifier/interface.rs
1use async_trait::async_trait;
2use thiserror::Error;
3
4use mithril_common::entities::{
5 Certificate, Epoch, ProtocolMessage, SignedEntityType, SignedEntityTypeDiscriminants,
6 SingleSignature,
7};
8use mithril_common::{StdError, StdResult};
9
10use crate::entities::OpenMessage;
11
12/// Errors dedicated to the CertifierService.
13#[derive(Debug, Error)]
14pub enum CertifierServiceError {
15 /// OpenMessage not found.
16 #[error("The open message was not found for beacon {0:?}.")]
17 NotFound(SignedEntityType),
18
19 /// The open message is already certified, no more single signatures may be
20 /// attached to it nor be certified again.
21 #[error("Open message for beacon {0:?} already certified.")]
22 AlreadyCertified(SignedEntityType),
23
24 /// The open message is expired, no more single signatures may be
25 /// attached to it nor be certified again.
26 #[error("Open message for beacon {0:?} is expired.")]
27 Expired(SignedEntityType),
28
29 /// An invalid signature was provided.
30 #[error("Invalid single signature for {0:?}.")]
31 InvalidSingleSignature(SignedEntityType, #[source] StdError),
32
33 /// No parent certificate could be found, this certifier cannot create genesis certificates.
34 #[error(
35 "No parent certificate could be found, this certifier cannot create genesis certificates."
36 )]
37 NoParentCertificateFound,
38
39 /// No certificate for this epoch
40 #[error(
41 "There is an epoch gap between the last certificate epoch ({certificate_epoch:?}) and current epoch ({current_epoch:?})"
42 )]
43 CertificateEpochGap {
44 /// Epoch of the last issued certificate
45 certificate_epoch: Epoch,
46
47 /// Given current epoch
48 current_epoch: Epoch,
49 },
50
51 /// Could not verify certificate chain because could not find last certificate.
52 #[error("No certificate found.")]
53 CouldNotFindLastCertificate,
54}
55
56/// Status of a successful registration of a single signature.
57#[derive(Debug, Copy, Clone, PartialEq)]
58pub enum SignatureRegistrationStatus {
59 /// The signature was registered and will be used for the next certificate.
60 Registered,
61
62 /// The signature was buffered, it will be used later.
63 Buffered,
64}
65
66/// ## CertifierService
67///
68/// This service manages the open message and their beacon transitions. It can
69/// ultimately transform open messages into certificates.
70#[cfg_attr(test, mockall::automock)]
71#[async_trait]
72pub trait CertifierService: Sync + Send {
73 /// Inform the certifier I have detected a new epoch, it may clear its state
74 /// and prepare the new signature round. If the given Epoch is equal or less
75 /// than the previous informed Epoch, nothing is done.
76 async fn inform_epoch(&self, epoch: Epoch) -> StdResult<()>;
77
78 /// Add a new single signature for the open message at the given beacon. If
79 /// the open message does not exist or the open message has been certified
80 /// since then, an error is returned.
81 async fn register_single_signature(
82 &self,
83 signed_entity_type: &SignedEntityType,
84 signature: &SingleSignature,
85 ) -> StdResult<SignatureRegistrationStatus>;
86
87 /// Create an open message at the given beacon. If the open message does not
88 /// exist or exists at an older beacon, the older open messages are cleared
89 /// along with their associated single signatures and the new open message
90 /// is created. If the message already exists, an error is returned.
91 async fn create_open_message(
92 &self,
93 signed_entity_type: &SignedEntityType,
94 protocol_message: &ProtocolMessage,
95 ) -> StdResult<OpenMessage>;
96
97 /// Return the open message at the given Beacon. If the message does not
98 /// exist, None is returned.
99 async fn get_open_message(
100 &self,
101 signed_entity_type: &SignedEntityType,
102 ) -> StdResult<Option<OpenMessage>>;
103
104 /// Mark the open message if it has expired.
105 async fn mark_open_message_if_expired(
106 &self,
107 signed_entity_type: &SignedEntityType,
108 ) -> StdResult<Option<OpenMessage>>;
109
110 /// Create a certificate if possible. If the pointed open message does
111 /// not exist or has been already certified, an error is raised. If a multi
112 /// signature is created then the flag `is_certified` of the open
113 /// message is set to true. The Certificate is created.
114 /// If the stake quorum of the single signatures is
115 /// not reached for the multisignature to be created, the certificate is not
116 /// created and None is returned. If the certificate can be created, the
117 /// list of the registered signers for the given epoch is used.
118 async fn create_certificate(
119 &self,
120 signed_entity_type: &SignedEntityType,
121 ) -> StdResult<Option<Certificate>>;
122
123 /// Returns a certificate from its hash.
124 async fn get_certificate_by_hash(&self, hash: &str) -> StdResult<Option<Certificate>>;
125
126 /// Returns the list of the latest created certificates.
127 async fn get_latest_certificates(&self, last_n: usize) -> StdResult<Vec<Certificate>>;
128
129 /// Verify the certificate chain and epoch gap. This will return an error if
130 /// there is at least an epoch between the given epoch and the most recent
131 /// certificate.
132 async fn verify_certificate_chain(&self, epoch: Epoch) -> StdResult<()>;
133}
134
135/// ## BufferedSingleSignatureStore
136///
137/// Allow to buffer single signatures for later use when an open message isn't available yet.
138#[cfg_attr(test, mockall::automock)]
139#[async_trait]
140pub trait BufferedSingleSignatureStore: Sync + Send {
141 /// Buffer a single signature for later use.
142 async fn buffer_signature(
143 &self,
144 signed_entity_type_discriminant: SignedEntityTypeDiscriminants,
145 signature: &SingleSignature,
146 ) -> StdResult<()>;
147
148 /// Get the buffered single signatures for the given signed entity discriminant.
149 async fn get_buffered_signatures(
150 &self,
151 signed_entity_type_discriminant: SignedEntityTypeDiscriminants,
152 ) -> StdResult<Vec<SingleSignature>>;
153
154 /// Remove the given single signatures from the buffer.
155 async fn remove_buffered_signatures(
156 &self,
157 signed_entity_type_discriminant: SignedEntityTypeDiscriminants,
158 single_signatures: Vec<SingleSignature>,
159 ) -> StdResult<()>;
160}