Skip to main content

forest/rpc/methods/
common.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use crate::lotus_json::lotus_json_with_self;
5use crate::rpc::error::ServerError;
6use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod};
7use enumflags2::BitFlags;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use std::sync::LazyLock;
11use uuid::Uuid;
12
13static SESSION_UUID: LazyLock<Uuid> = LazyLock::new(crate::utils::rand::new_uuid_v4);
14
15/// The returned session UUID uniquely identifies the API node.
16pub enum Session {}
17impl RpcMethod<0> for Session {
18    const NAME: &'static str = "Filecoin.Session";
19    const PARAM_NAMES: [&'static str; 0] = [];
20    const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
21    const PERMISSION: Permission = Permission::Read;
22    const DESCRIPTION: &'static str =
23        "Returns a UUID that uniquely identifies this node for the current session.";
24
25    type Params = ();
26    type Ok = Uuid;
27
28    async fn handle(_: Ctx, (): Self::Params, _: &http::Extensions) -> Result<Uuid, ServerError> {
29        Ok(*SESSION_UUID)
30    }
31}
32
33pub enum Version {}
34impl RpcMethod<0> for Version {
35    const NAME: &'static str = "Filecoin.Version";
36    const PARAM_NAMES: [&'static str; 0] = [];
37    const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
38    const PERMISSION: Permission = Permission::Read;
39    const DESCRIPTION: &'static str = "Returns the node version, API version, and block delay.";
40
41    type Params = ();
42    type Ok = PublicVersion;
43
44    async fn handle(
45        ctx: Ctx,
46        (): Self::Params,
47        ext: &http::Extensions,
48    ) -> Result<Self::Ok, ServerError> {
49        // Report the API version for the endpoint actually being served, so V0
50        // clients (e.g. lotus-miner over `/rpc/v0`) accept the version handshake.
51        // Values from Lotus `api/version.go`: <https://github.com/filecoin-project/lotus/blob/27abf0f16a7f2a83305910f3c2a1844764d20b75/api/version.go#L57-L58>
52        let api_version = match ext.get::<ApiPaths>() {
53            Some(ApiPaths::V0) => ShiftingVersion::new(1, 5, 0),
54            Some(ApiPaths::V1 | ApiPaths::V2) | None => ShiftingVersion::new(2, 3, 0),
55        };
56        Ok(PublicVersion {
57            version: crate::utils::version::FOREST_VERSION_STRING.clone(),
58            api_version,
59            block_delay: ctx.chain_config().block_delay_secs,
60            agent: "forest".into(),
61        })
62    }
63}
64
65pub enum Shutdown {}
66impl RpcMethod<0> for Shutdown {
67    const NAME: &'static str = "Filecoin.Shutdown";
68    const PARAM_NAMES: [&'static str; 0] = [];
69    const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
70    const PERMISSION: Permission = Permission::Admin;
71    const DESCRIPTION: &'static str = "Shuts the node down.";
72
73    type Params = ();
74    type Ok = ();
75
76    async fn handle(
77        ctx: Ctx,
78        (): Self::Params,
79        _: &http::Extensions,
80    ) -> Result<Self::Ok, ServerError> {
81        ctx.shutdown.send(()).await?;
82        Ok(())
83    }
84}
85
86pub enum StartTime {}
87impl RpcMethod<0> for StartTime {
88    const NAME: &'static str = "Filecoin.StartTime";
89    const PARAM_NAMES: [&'static str; 0] = [];
90    const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
91    const PERMISSION: Permission = Permission::Read;
92    const DESCRIPTION: &'static str = "Returns the time at which the node was started.";
93
94    type Params = ();
95    type Ok = chrono::DateTime<chrono::Utc>;
96
97    async fn handle(
98        ctx: Ctx,
99        (): Self::Params,
100        _: &http::Extensions,
101    ) -> Result<Self::Ok, ServerError> {
102        Ok(ctx.start_time)
103    }
104}
105
106/// Represents the current version of the API.
107#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
108#[serde(rename_all = "PascalCase")]
109pub struct PublicVersion {
110    pub version: String,
111    #[serde(rename = "APIVersion")]
112    pub api_version: ShiftingVersion,
113    pub block_delay: u32,
114    // See <https://github.com/filecoin-project/lotus/blob/a0ecb8687f1c60d5e66040b6de364dbc9cc4d253/api/api_common.go#L78>
115    pub agent: String,
116}
117lotus_json_with_self!(PublicVersion);
118
119/// Integer based value on version information. Highest order bits for Major,
120/// Mid order for Minor and lowest for Patch.
121#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
122pub struct ShiftingVersion(u32);
123
124impl ShiftingVersion {
125    pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
126        Self(((major as u32) << 16) | ((minor as u32) << 8) | (patch as u32))
127    }
128}