mithril_aggregator/services/signable_builder/
signable_seed_builder.rs

1//! ## AggregatorSignableSeedBuilder
2//!
3//! This service is responsible for computing the seed protocol message
4//! that is used by the [SignableBuilder] to compute the final protocol message.
5//!
6use anyhow::Context;
7use async_trait::async_trait;
8use std::sync::Arc;
9use tokio::sync::RwLock;
10
11use mithril_common::{
12    StdResult, crypto_helper::ProtocolKey, entities::ProtocolMessagePartValue,
13    signable_builder::SignableSeedBuilder,
14};
15
16use crate::services::EpochService;
17
18/// SignableSeedBuilder aggregator implementation
19pub struct AggregatorSignableSeedBuilder {
20    epoch_service: Arc<RwLock<dyn EpochService>>,
21}
22
23impl AggregatorSignableSeedBuilder {
24    /// AggregatorSignableSeedBuilder factory
25    pub fn new(epoch_service: Arc<RwLock<dyn EpochService>>) -> Self {
26        Self { epoch_service }
27    }
28}
29
30#[async_trait]
31impl SignableSeedBuilder for AggregatorSignableSeedBuilder {
32    async fn compute_next_aggregate_verification_key_for_concatenation(
33        &self,
34    ) -> StdResult<ProtocolMessagePartValue> {
35        let epoch_service = self.epoch_service.read().await;
36        let next_aggregate_verification_key = ProtocolKey::new(
37            (*epoch_service)
38                .next_aggregate_verification_key()?
39                .to_concatenation_aggregate_verification_key()
40                .to_owned(),
41        )
42        .to_json_hex()
43        .with_context(|| "convert next avk to json hex failure")?
44        .to_string();
45
46        Ok(next_aggregate_verification_key)
47    }
48
49    async fn compute_next_protocol_parameters(&self) -> StdResult<ProtocolMessagePartValue> {
50        let epoch_service = self.epoch_service.read().await;
51        let next_protocol_parameters = epoch_service.next_protocol_parameters()?.compute_hash();
52
53        Ok(next_protocol_parameters)
54    }
55
56    async fn compute_current_epoch(&self) -> StdResult<ProtocolMessagePartValue> {
57        let epoch_service = self.epoch_service.read().await;
58        let current_epoch = epoch_service.epoch_of_current_data()?.to_string();
59
60        Ok(current_epoch)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use mithril_common::{
67        entities::Epoch,
68        test::{
69            builder::{MithrilFixture, MithrilFixtureBuilder},
70            double::Dummy,
71        },
72    };
73
74    use crate::{entities::AggregatorEpochSettings, services::FakeEpochServiceBuilder};
75
76    use super::*;
77
78    fn build_signable_builder_service(
79        epoch: Epoch,
80        fixture: &MithrilFixture,
81        next_fixture: &MithrilFixture,
82    ) -> AggregatorSignableSeedBuilder {
83        let epoch_service = Arc::new(RwLock::new(
84            FakeEpochServiceBuilder {
85                current_epoch_settings: AggregatorEpochSettings {
86                    protocol_parameters: fixture.protocol_parameters(),
87                    ..AggregatorEpochSettings::dummy()
88                },
89                next_epoch_settings: AggregatorEpochSettings {
90                    protocol_parameters: next_fixture.protocol_parameters(),
91                    ..AggregatorEpochSettings::dummy()
92                },
93                signer_registration_epoch_settings: AggregatorEpochSettings {
94                    protocol_parameters: next_fixture.protocol_parameters(),
95                    ..AggregatorEpochSettings::dummy()
96                },
97                current_signers_with_stake: fixture.signers_with_stake(),
98                next_signers_with_stake: next_fixture.signers_with_stake(),
99                ..FakeEpochServiceBuilder::dummy(epoch)
100            }
101            .build(),
102        ));
103
104        AggregatorSignableSeedBuilder::new(epoch_service)
105    }
106
107    #[tokio::test]
108    async fn test_compute_next_aggregate_verification_key_protocol_message_value() {
109        let epoch = Epoch(5);
110        let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
111        let next_fixture = MithrilFixtureBuilder::default().with_signers(4).build();
112        let signable_seed_builder = build_signable_builder_service(epoch, &fixture, &next_fixture);
113        let expected_next_aggregate_verification_key =
114            next_fixture.compute_and_encode_concatenation_aggregate_verification_key();
115
116        let next_aggregate_verification_key = signable_seed_builder
117            .compute_next_aggregate_verification_key_for_concatenation()
118            .await
119            .unwrap();
120
121        assert_eq!(
122            next_aggregate_verification_key,
123            expected_next_aggregate_verification_key
124        );
125    }
126
127    #[tokio::test]
128    async fn test_compute_next_protocol_parameters_protocol_message_value() {
129        let epoch = Epoch(5);
130        let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
131        let next_fixture = MithrilFixtureBuilder::default().with_signers(4).build();
132        let signable_seed_builder = build_signable_builder_service(epoch, &fixture, &next_fixture);
133        let expected_next_protocol_parameters = next_fixture.protocol_parameters().compute_hash();
134
135        let next_protocol_parameters = signable_seed_builder
136            .compute_next_protocol_parameters()
137            .await
138            .unwrap();
139
140        assert_eq!(next_protocol_parameters, expected_next_protocol_parameters);
141    }
142
143    #[tokio::test]
144    async fn test_compute_current_epoch_protocol_message_value() {
145        let epoch = Epoch(5);
146        let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
147        let next_fixture = MithrilFixtureBuilder::default().with_signers(4).build();
148        let signable_seed_builder = build_signable_builder_service(epoch, &fixture, &next_fixture);
149        let expected_current_epoch = epoch.to_string();
150
151        let current_epoch = signable_seed_builder.compute_current_epoch().await.unwrap();
152
153        assert_eq!(current_epoch, expected_current_epoch);
154    }
155}