use slog::Logger;
use std::sync::Arc;
use tokio::sync::RwLock;
use mithril_common::{
api_version::APIVersionProvider,
cardano_block_scanner::BlockScanner,
certificate_chain::CertificateVerifier,
chain_observer::ChainObserver,
crypto_helper::ProtocolGenesisVerifier,
digesters::{ImmutableDigester, ImmutableFileObserver},
entities::{
CardanoTransactionsSigningConfig, Epoch, ProtocolParameters, SignerWithStake,
StakeDistribution,
},
era::{EraChecker, EraReader},
signable_builder::SignableBuilderService,
signed_entity_type_lock::SignedEntityTypeLock,
test_utils::MithrilFixture,
TickerService,
};
use mithril_persistence::{
sqlite::{SqliteConnection, SqliteConnectionPool},
store::StakeStorer,
};
use crate::{
configuration::*,
database::repository::{
CertificateRepository, OpenMessageRepository, SignedEntityStorer, SignerGetter,
StakePoolStore,
},
entities::AggregatorEpochSettings,
event_store::{EventMessage, TransmitterService},
multi_signer::MultiSigner,
services::{
CertifierService, EpochService, MessageService, ProverService, SignedEntityService,
StakeDistributionService, TransactionStore, UpkeepService,
},
signer_registerer::SignerRecorder,
snapshot_uploaders::SnapshotUploader,
CertificatePendingStore, EpochSettingsStorer, MetricsService, SignerRegisterer,
SignerRegistrationRoundOpener, SingleSignatureAuthenticator, Snapshotter,
VerificationKeyStorer,
};
pub type EpochServiceWrapper = Arc<RwLock<dyn EpochService>>;
pub struct DependencyContainer {
#[deprecated]
pub config: Configuration,
pub root_logger: Logger,
pub sqlite_connection: Arc<SqliteConnection>,
pub sqlite_connection_cardano_transaction_pool: Arc<SqliteConnectionPool>,
pub stake_store: Arc<StakePoolStore>,
pub snapshot_uploader: Arc<dyn SnapshotUploader>,
pub multi_signer: Arc<dyn MultiSigner>,
pub certificate_pending_store: Arc<CertificatePendingStore>,
pub certificate_repository: Arc<CertificateRepository>,
pub open_message_repository: Arc<OpenMessageRepository>,
pub verification_key_store: Arc<dyn VerificationKeyStorer>,
pub epoch_settings_storer: Arc<dyn EpochSettingsStorer>,
pub chain_observer: Arc<dyn ChainObserver>,
pub transaction_store: Arc<dyn TransactionStore>,
pub block_scanner: Arc<dyn BlockScanner>,
pub immutable_file_observer: Arc<dyn ImmutableFileObserver>,
pub digester: Arc<dyn ImmutableDigester>,
pub snapshotter: Arc<dyn Snapshotter>,
pub certificate_verifier: Arc<dyn CertificateVerifier>,
pub genesis_verifier: Arc<ProtocolGenesisVerifier>,
pub signer_registerer: Arc<dyn SignerRegisterer>,
pub signer_registration_round_opener: Arc<dyn SignerRegistrationRoundOpener>,
pub era_checker: Arc<EraChecker>,
pub era_reader: Arc<EraReader>,
pub event_transmitter: Arc<TransmitterService<EventMessage>>,
pub api_version_provider: Arc<APIVersionProvider>,
pub stake_distribution_service: Arc<dyn StakeDistributionService>,
pub signer_recorder: Arc<dyn SignerRecorder>,
pub signable_builder_service: Arc<dyn SignableBuilderService>,
pub signed_entity_service: Arc<dyn SignedEntityService>,
pub certifier_service: Arc<dyn CertifierService>,
pub epoch_service: EpochServiceWrapper,
pub ticker_service: Arc<dyn TickerService>,
pub signed_entity_storer: Arc<dyn SignedEntityStorer>,
pub signer_getter: Arc<dyn SignerGetter>,
pub message_service: Arc<dyn MessageService>,
pub prover_service: Arc<dyn ProverService>,
pub signed_entity_type_lock: Arc<SignedEntityTypeLock>,
pub upkeep_service: Arc<dyn UpkeepService>,
pub single_signer_authenticator: Arc<SingleSignatureAuthenticator>,
pub metrics_service: Arc<MetricsService>,
}
#[doc(hidden)]
impl DependencyContainer {
pub async fn get_genesis_epochs(&self) -> (Epoch, Epoch) {
let current_epoch = self
.chain_observer
.get_current_epoch()
.await
.expect("get_current_epoch should not fail")
.expect("an epoch should've been set to the chain observer");
let work_epoch = current_epoch
.offset_to_signer_retrieval_epoch()
.expect("epoch.offset_by SIGNER_EPOCH_RETRIEVAL_OFFSET should not fail");
let epoch_to_sign = current_epoch.offset_to_next_signer_retrieval_epoch();
(work_epoch, epoch_to_sign)
}
pub async fn init_state_from_fixture(&self, fixture: &MithrilFixture, target_epochs: &[Epoch]) {
for epoch in target_epochs {
self.epoch_settings_storer
.save_epoch_settings(
*epoch,
#[allow(deprecated)]
AggregatorEpochSettings {
protocol_parameters: fixture.protocol_parameters(),
cardano_transactions_signing_config: self
.config
.cardano_transactions_signing_config
.clone(),
},
)
.await
.expect("save_epoch_settings should not fail");
self.fill_verification_key_store(*epoch, &fixture.signers_with_stake())
.await;
self.fill_stakes_store(*epoch, fixture.signers_with_stake())
.await;
}
}
pub async fn prepare_for_genesis(
&self,
genesis_signers: Vec<SignerWithStake>,
second_epoch_signers: Vec<SignerWithStake>,
genesis_protocol_parameters: &ProtocolParameters,
cardano_transactions_signing_config: &CardanoTransactionsSigningConfig,
) {
self.init_epoch_settings_storer(&AggregatorEpochSettings {
protocol_parameters: genesis_protocol_parameters.clone(),
cardano_transactions_signing_config: cardano_transactions_signing_config.clone(),
})
.await;
let (work_epoch, epoch_to_sign) = self.get_genesis_epochs().await;
for (epoch, signers) in [
(work_epoch, genesis_signers),
(epoch_to_sign, second_epoch_signers),
] {
self.fill_verification_key_store(epoch, &signers).await;
self.fill_stakes_store(epoch, signers).await;
}
}
pub async fn init_epoch_settings_storer(&self, epoch_settings: &AggregatorEpochSettings) {
let (work_epoch, epoch_to_sign) = self.get_genesis_epochs().await;
let mut epochs_to_save = Vec::new();
epochs_to_save.push(work_epoch);
epochs_to_save.push(epoch_to_sign);
epochs_to_save.push(epoch_to_sign.next());
for epoch in epochs_to_save {
self.epoch_settings_storer
.save_epoch_settings(epoch, epoch_settings.clone())
.await
.expect("save_epoch_settings should not fail");
}
}
async fn fill_verification_key_store(&self, target_epoch: Epoch, signers: &[SignerWithStake]) {
for signer in signers {
self.signer_recorder
.record_signer_registration(signer.party_id.clone())
.await
.expect("record_signer_registration should not fail");
self.verification_key_store
.save_verification_key(target_epoch, signer.clone())
.await
.expect("save_verification_key should not fail");
}
}
async fn fill_stakes_store(&self, target_epoch: Epoch, signers: Vec<SignerWithStake>) {
let _ = self
.stake_store
.save_stakes(
target_epoch,
signers
.iter()
.map(|s| s.into())
.collect::<StakeDistribution>(),
)
.await
.expect("save_stakes should not fail");
}
}
#[cfg(test)]
pub mod tests {
use crate::{dependency_injection::DependenciesBuilder, Configuration, DependencyContainer};
pub async fn initialize_dependencies() -> DependencyContainer {
let config = Configuration::new_sample();
let mut builder = DependenciesBuilder::new_with_stdout_logger(config);
builder.build_dependency_container().await.unwrap()
}
}