ab_farmer/
node_client.rs

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