Skip to main content

tycho_control/
proto.rs

1use std::net::SocketAddr;
2use std::num::{NonZeroU32, NonZeroU64};
3
4use bytes::Bytes;
5use serde::{Deserialize, Serialize};
6use tycho_types::models::{
7    BlockId, BlockIdShort, BlockchainConfig, GlobalVersion, ShardAccount, StdAddr,
8};
9use tycho_types::prelude::*;
10use tycho_util::{FastHashSet, serde_helpers};
11
12use crate::error::ServerResult;
13use crate::mempool;
14
15#[tarpc::service]
16pub trait ControlServer {
17    /// Ping a node. Returns node timestamp in milliseconds.
18    async fn ping() -> u64;
19
20    /// Get node status.
21    async fn get_status() -> ServerResult<NodeStatusResponse>;
22
23    /// Trigger manual GC for archives.
24    async fn trigger_archives_gc(req: TriggerGcRequest);
25
26    /// Trigger manual GC for blocks.
27    async fn trigger_blocks_gc(req: TriggerGcRequest);
28
29    /// Trigger manual GC for states.
30    async fn trigger_states_gc(req: TriggerGcRequest);
31
32    /// Trigger manual compaction.
33    async fn trigger_compaction(req: TriggerCompactionRequest);
34
35    /// Sets memory profiler state. Returns whether the state was changed.
36    async fn set_memory_profiler_enabled(enabled: bool) -> bool;
37
38    /// Returns memory profiler dump.
39    async fn dump_memory_profiler() -> ServerResult<Vec<u8>>;
40
41    /// Get node neighbours info
42    async fn get_neighbours_info() -> ServerResult<NeighboursInfoResponse>;
43
44    /// Broadcast a message to validators.
45    async fn broadcast_external_message(req: BroadcastExtMsgRequest) -> ServerResult<()>;
46
47    /// Get account state.
48    async fn get_account_state(req: AccountStateRequest) -> ServerResult<AccountStateResponse>;
49
50    /// Get blockchain config.
51    async fn get_blockchain_config() -> ServerResult<BlockchainConfigResponse>;
52
53    /// Get block bytes
54    async fn get_block(req: BlockRequest) -> ServerResult<BlockResponse>;
55
56    /// Get proof bytes.
57    async fn get_block_proof(req: BlockRequest) -> ServerResult<BlockResponse>;
58
59    /// Get queue bytes.
60    async fn get_queue_diff(req: BlockRequest) -> ServerResult<BlockResponse>;
61
62    /// Get archive id
63    async fn get_archive_info(req: ArchiveInfoRequest) -> ServerResult<ArchiveInfoResponse>;
64
65    /// Download archive slice.
66    async fn get_archive_chunk(req: ArchiveSliceRequest) -> ServerResult<ArchiveSliceResponse>;
67
68    /// Returns list of all archive ids.
69    async fn get_archive_ids() -> ServerResult<Vec<ArchiveInfo>>;
70
71    /// Returns list of all block ids.
72    async fn get_block_ids(req: BlockListRequest) -> ServerResult<BlockListResponse>;
73
74    /// Returns list of all overlays.
75    async fn get_overlay_ids() -> ServerResult<OverlayIdsResponse>;
76
77    /// Get overlay peers.
78    async fn get_overlay_peers(req: OverlayPeersRequest) -> ServerResult<OverlayPeersResponse>;
79
80    /// Search for `k` closest nodes known to `peer_id` that store `key`.
81    async fn dht_find_node(req: DhtFindNodeRequest) -> ServerResult<DhtFindNodeResponse>;
82
83    /// Signs an elections payload.
84    async fn sign_elections_payload(
85        req: ElectionsPayloadRequest,
86    ) -> ServerResult<ElectionsPayloadResponse>;
87
88    /// Dumps the current in-memory moderator ban state.
89    async fn mempool_dump_bans() -> ServerResult<Vec<mempool::DumpBansItem>>;
90
91    /// Dumps the in-memory moderator event/toleration cache, not persisted journal rows.
92    async fn mempool_dump_events(req: mempool::DumpEventsRequest) -> ServerResult<String>;
93
94    /// Queues a manual ban and waits for persisted completion while the client stays connected.
95    /// After the node accepts the request, it cannot be cancelled (by timeout, disconnect, etc.).
96    async fn mempool_ban(req: mempool::BanRequest) -> ServerResult<String>;
97
98    /// Queues a manual unban and waits for persisted completion while the client stays connected.
99    /// Live visibility can lag because the peer must resolve again after unban.
100    /// After the node accepts the request, it cannot be cancelled (by timeout, disconnect, etc.).
101    async fn mempool_unban(peer_id: HashBytes) -> ServerResult<()>;
102
103    /// Lists persisted moderator journal records of all types.
104    /// Point key with `stored=true` can be used to retrieve full point with a separate call.
105    async fn mempool_list_events(
106        req: mempool::ListEventsRequest,
107    ) -> ServerResult<Vec<mempool::MempoolEventDisplay>>;
108
109    /// Deletes persisted moderator journal data only; does not mutate in-mem moderator state.
110    /// After the node accepts the request, it cannot be cancelled (by timeout, disconnect, etc.).
111    async fn mempool_delete_events(millis: std::ops::Range<u64>) -> ServerResult<()>;
112
113    /// Loads a point linked from a stored moderator journal record (if its key has `stored` flag)
114    async fn mempool_get_event_point(key: mempool::PointKey) -> ServerResult<Bytes>;
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct NodeStatusResponse {
119    pub status_at: u32,
120    pub node_info: NodeInfo,
121    pub init_block_id: Option<BlockId>,
122    pub last_applied_block: Option<LastAppliedBlock>,
123    pub validator_status: Option<ValidatorStatus>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct NodeInfo {
128    pub version: String,
129    pub build: String,
130
131    // TODO: Somehow expose tycho_network::Address?
132    pub public_addr: String,
133    pub local_addr: SocketAddr,
134    pub adnl_id: HashBytes,
135    pub collator: Option<CollatorInfo>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct LastAppliedBlock {
140    pub block_id: BlockId,
141    pub gen_utime: u32,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct ValidatorStatus {
146    pub public_key: HashBytes,
147    pub in_current_vset: bool,
148    pub in_next_vset: bool,
149    pub is_elected: bool,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct CollatorInfo {
154    pub global_version: GlobalVersion,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
158pub enum TriggerGcRequest {
159    Exact(u32),
160    Distance(u32),
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct TriggerCompactionRequest {
165    pub database: String,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct BroadcastExtMsgRequest {
170    /// A BOC with a [`Message`].
171    ///
172    /// [`Message`]: tycho_types::models::Message
173    pub message: Bytes,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct AccountStateRequest {
178    pub address: StdAddr,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct AccountStateResponse {
183    pub mc_seqno: u32,
184    pub gen_utime: u32,
185
186    /// A BOC with a [`ShardAccount`].
187    ///
188    /// NOTE: [`BocRepr`] cannot be safely used here because
189    /// we must hold a state tracker handle to delay the GC,
190    /// and it is very inconvenient to pass it around here.
191    pub state: Bytes,
192}
193
194impl AccountStateResponse {
195    pub fn parse(&self) -> Result<ParsedAccountState, tycho_types::boc::BocReprError> {
196        Ok(ParsedAccountState {
197            mc_seqno: self.mc_seqno,
198            gen_utime: self.gen_utime,
199            state: BocRepr::decode(&self.state)?,
200        })
201    }
202}
203
204#[derive(Debug, Clone, Serialize)]
205pub struct ParsedAccountState {
206    pub mc_seqno: u32,
207    pub gen_utime: u32,
208    #[serde(flatten)]
209    pub state: ShardAccount,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct BlockchainConfigResponse {
214    pub global_id: i32,
215    pub mc_seqno: u32,
216    pub gen_utime: u32,
217
218    /// A BOC with a [`BlockchainConfig`].
219    pub config: Bytes,
220}
221
222impl BlockchainConfigResponse {
223    pub fn parse(&self) -> Result<ParsedBlockchainConfigResponse, tycho_types::boc::BocReprError> {
224        Ok(ParsedBlockchainConfigResponse {
225            global_id: self.global_id,
226            mc_seqno: self.mc_seqno,
227            gen_utime: self.gen_utime,
228            config: BocRepr::decode(&self.config)?,
229        })
230    }
231}
232
233#[derive(Debug, Clone, Serialize)]
234pub struct ParsedBlockchainConfigResponse {
235    pub global_id: i32,
236    pub mc_seqno: u32,
237    pub gen_utime: u32,
238    #[serde(flatten)]
239    pub config: BlockchainConfig,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct BlockRequest {
244    pub block_id: BlockId,
245}
246
247#[derive(Debug, Serialize, Deserialize)]
248pub enum BlockResponse {
249    Found { data: Bytes },
250    NotFound,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct ArchiveInfoRequest {
255    pub mc_seqno: u32,
256}
257
258#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
259pub struct ArchiveInfo {
260    pub id: u32,
261    pub size: NonZeroU64,
262    pub chunk_size: NonZeroU32,
263}
264
265#[derive(Debug, Serialize, Deserialize)]
266pub enum ArchiveInfoResponse {
267    Found(ArchiveInfo),
268    TooNew,
269    NotFound,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct ArchiveSliceRequest {
274    pub archive_id: u32,
275    pub offset: u64,
276}
277
278#[derive(Debug, Serialize, Deserialize)]
279pub struct ArchiveSliceResponse {
280    pub data: Bytes,
281}
282
283#[derive(Debug, Serialize, Deserialize)]
284pub struct BlockListRequest {
285    pub continuation: Option<BlockIdShort>,
286}
287
288#[derive(Debug, Serialize, Deserialize)]
289pub struct BlockListResponse {
290    pub blocks: Vec<BlockId>,
291    pub continuation: Option<BlockIdShort>,
292}
293
294#[derive(Debug, Serialize, Deserialize)]
295pub struct ElectionsPayloadRequest {
296    pub election_id: u32,
297    pub address: HashBytes,
298    pub stake_factor: u32,
299    pub public_key: HashBytes,
300    pub adnl_addr: HashBytes,
301    pub global_id: i32,
302    pub capabilities: u64,
303}
304
305#[derive(Debug, Serialize, Deserialize)]
306pub struct ElectionsPayloadResponse {
307    // TODO: Add `serde(with = "base64")`
308    pub data: Bytes,
309    pub public_key: HashBytes,
310    #[serde(with = "serde_helpers::signature")]
311    pub signature: Box<[u8; 64]>,
312}
313
314#[derive(Debug, Serialize, Deserialize)]
315pub struct NeighboursInfoResponse {
316    pub neighbours: Vec<NeighbourInfo>,
317}
318
319#[derive(Debug, Serialize, Deserialize)]
320pub struct NeighbourInfo {
321    pub id: HashBytes,
322    pub expires_at: u32,
323    pub score: u8,
324    pub failed_requests: u64,
325    pub total_requests: u64,
326    pub roundtrip_ms: u64,
327}
328
329#[derive(Debug, Serialize, Deserialize)]
330pub struct OverlayIdsResponse {
331    pub public_overlays: FastHashSet<HashBytes>,
332    pub private_overlays: FastHashSet<HashBytes>,
333}
334
335#[derive(Debug, Serialize, Deserialize)]
336pub struct OverlayPeersRequest {
337    pub overlay_id: HashBytes,
338}
339
340#[derive(Debug, Serialize, Deserialize)]
341pub struct OverlayPeersResponse {
342    pub overlay_type: OverlayType,
343    pub peers: Vec<OverlayPeer>,
344}
345
346#[derive(Debug, Serialize, Deserialize)]
347pub struct OverlayPeer {
348    pub peer_id: HashBytes,
349    pub entry_created_at: Option<u32>,
350    pub info: Option<PeerInfo>,
351}
352
353#[derive(Debug, Serialize, Deserialize)]
354pub enum OverlayType {
355    Private,
356    Public,
357}
358
359#[derive(Debug, Serialize, Deserialize)]
360pub struct DhtFindNodeRequest {
361    /// Remove peer id or `None` for local.
362    pub peer_id: Option<HashBytes>,
363    pub key: HashBytes,
364    pub k: u32,
365}
366
367#[derive(Debug, Serialize, Deserialize)]
368pub struct DhtFindNodeResponse {
369    pub nodes: Vec<DhtFindNodeResponseItem>,
370}
371
372#[derive(Debug, Serialize, Deserialize)]
373pub struct DhtFindNodeResponseItem {
374    pub peer_id: HashBytes,
375    pub info: PeerInfo,
376}
377
378#[derive(Debug, Serialize, Deserialize)]
379pub struct PeerInfo {
380    pub address_list: Vec<String>,
381    pub created_at: u32,
382    pub expires_at: u32,
383}