Skip to main content

ab_farmer/
node_client.rs

1//! Node client abstraction
2//!
3//! During farmer operation it needs to communicate with a node, for example, to receive slot
4//! notifications and send solutions to seal blocks.
5//!
6//! Implementation is abstracted away behind a trait to allow various implementations depending on
7//! the use case. Implementation may connect to a node via RPC directly, through some kind of
8//! networked middleware, or even wired without a network directly if node and farmer are both
9//! running in the same process.
10
11pub mod caching_proxy_node_client;
12pub mod rpc_node_client;
13
14use ab_core_primitives::pieces::{Piece, PieceIndex};
15use ab_core_primitives::segments::{
16    SegmentIndex, SuperSegmentHeader, SuperSegmentIndex, SuperSegmentRoot,
17};
18use ab_farmer_rpc_primitives::{
19    BlockSealInfo, BlockSealResponse, FarmerAppInfo, FarmerShardMembershipInfo, SlotInfo,
20    SolutionResponse,
21};
22use async_trait::async_trait;
23use futures::Stream;
24use std::fmt;
25use std::pin::Pin;
26
27/// Abstraction of the Node Client
28#[async_trait]
29pub trait NodeClient: fmt::Debug + Send + Sync + 'static {
30    /// Get farmer app info
31    async fn farmer_app_info(&self) -> anyhow::Result<FarmerAppInfo>;
32
33    /// Subscribe to slot
34    async fn subscribe_slot_info(
35        &self,
36    ) -> anyhow::Result<Pin<Box<dyn Stream<Item = SlotInfo> + Send + 'static>>>;
37
38    /// Submit a slot solution
39    async fn submit_solution_response(
40        &self,
41        solution_response: SolutionResponse,
42    ) -> anyhow::Result<()>;
43
44    /// Subscribe to block sealing requests
45    async fn subscribe_block_sealing(
46        &self,
47    ) -> anyhow::Result<Pin<Box<dyn Stream<Item = BlockSealInfo> + Send + 'static>>>;
48
49    /// Submit a block seal
50    async fn submit_block_seal(&self, block_seal: BlockSealResponse) -> anyhow::Result<()>;
51
52    /// Subscribe to new super segment headers
53    async fn subscribe_new_super_segment_headers(
54        &self,
55    ) -> anyhow::Result<Pin<Box<dyn Stream<Item = SuperSegmentHeader> + Send + 'static>>>;
56
57    /// Get super segment headers
58    async fn super_segment_headers(
59        &self,
60        super_segment_indices: Vec<SuperSegmentIndex>,
61    ) -> anyhow::Result<Vec<Option<SuperSegmentHeader>>>;
62
63    /// Get super segment root for a segment index
64    async fn super_segment_root_for_segment_index(
65        &self,
66        segment_index: SegmentIndex,
67    ) -> anyhow::Result<Option<SuperSegmentRoot>>;
68
69    /// Get piece by index
70    async fn piece(&self, piece_index: PieceIndex) -> anyhow::Result<Option<Piece>>;
71
72    // TODO: Move into `NodeClientExt`?
73    /// Must be called while there is an active `shard_membership_entropy_update` subscription
74    async fn update_shard_membership_info(
75        &self,
76        info: FarmerShardMembershipInfo,
77    ) -> anyhow::Result<()>;
78}
79
80/// Node Client extension methods that are not necessary for a farmer as a library but might be
81/// useful for an app
82#[async_trait]
83pub trait NodeClientExt: NodeClient {
84    /// Get the cached super segment headers for the given super segment indices.
85    /// If there is a cache, it is not updated to avoid remote denial of service.
86    ///
87    /// Returns `None` for super segment indices that are not in the cache.
88    async fn cached_super_segment_headers(
89        &self,
90        super_segment_indices: Vec<SuperSegmentIndex>,
91    ) -> anyhow::Result<Vec<Option<SuperSegmentHeader>>>;
92
93    /// Get up to `limit` most recent super segment headers.
94    /// If there is a cache, it is not updated to avoid remote denial of service.
95    ///
96    /// If the node or cache has less than `limit` super segment headers, the returned vector will
97    /// be shorter. Each returned super segment header is wrapped in `Some`.
98    async fn last_super_segment_headers(
99        &self,
100        limit: u32,
101    ) -> anyhow::Result<Vec<Option<SuperSegmentHeader>>>;
102}