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