Skip to main content

espresso_node/request_response/
recipient_source.rs

1use std::sync::Arc;
2
3use anyhow::{Context, Result};
4use async_trait::async_trait;
5use espresso_types::{PubKey, SeqTypes, traits::SequencerPersistence};
6use hotshot_types::{data::EpochNumber, epoch_membership::EpochMembershipCoordinator};
7use request_response::recipient_source::RecipientSource as RecipientSourceTrait;
8use tracing::warn;
9
10use super::request::Request;
11use crate::consensus_handle::ConsensusHandle;
12
13#[derive(Clone)]
14pub struct RecipientSource<P: SequencerPersistence> {
15    pub consensus_handle: Arc<ConsensusHandle<SeqTypes, Arc<P>>>,
16    /// A copy of the membership coordinator
17    pub memberships: EpochMembershipCoordinator<SeqTypes>,
18    /// The public key of the node
19    pub public_key: PubKey,
20}
21
22/// Implement the RecipientSourceTrait, which allows the request-response protocol to derive the
23/// intended recipients for a given request
24#[async_trait]
25impl<P: SequencerPersistence> RecipientSourceTrait<Request, PubKey> for RecipientSource<P> {
26    async fn get_expected_responders(&self, _request: &Request) -> Result<Vec<PubKey>> {
27        // Get the current epoch number
28        let epoch_number = self
29            .consensus_handle
30            .current_epoch()
31            .await
32            .unwrap_or(EpochNumber::genesis());
33
34        // Attempt to get the membership for the current epoch
35        let membership = match self.memberships.stake_table_for_epoch(Some(epoch_number)) {
36            Ok(membership) => membership,
37            Err(e) => {
38                warn!(
39                    "Failed to get membership for epoch {}: {e:#}. Failing over to previous epoch",
40                    epoch_number
41                );
42                let prev_epoch = epoch_number.saturating_sub(1);
43                self.memberships
44                    .stake_table_for_epoch(Some(EpochNumber::new(prev_epoch)))
45                    .with_context(|| "failed to get stake table for epoch")?
46            },
47        };
48
49        // Sum all participants in the membership
50        Ok(membership
51            .stake_table()
52            .map(|entry| entry.stake_table_entry.stake_key)
53            .filter(|key| *key != self.public_key)
54            .collect())
55    }
56}