stratus/eth/external_rpc/
mod.rs

1pub use postgres::PostgresExternalRpc;
2pub use postgres::PostgresExternalRpcConfig;
3
4mod postgres;
5
6use std::str::FromStr;
7use std::sync::Arc;
8use std::time::Duration;
9
10use anyhow::anyhow;
11use clap::Parser;
12use display_json::DebugAsJson;
13
14use crate::alias::JsonValue;
15use crate::eth::primitives::Account;
16use crate::eth::primitives::Address;
17use crate::eth::primitives::BlockNumber;
18use crate::eth::primitives::ExternalBlock;
19use crate::eth::primitives::ExternalReceipt;
20use crate::eth::primitives::Hash;
21use crate::eth::primitives::Wei;
22use crate::ext::parse_duration;
23
24pub type ExternalBlockWithReceipts = (ExternalBlock, Vec<ExternalReceipt>);
25
26#[allow(async_fn_in_trait)]
27pub trait ExternalRpc: Send + Sync {
28    /// Read the largest block number saved inside a block range.
29    async fn read_max_block_number_in_range(&self, start: BlockNumber, end: BlockNumber) -> anyhow::Result<Option<BlockNumber>>;
30
31    /// Read all blocks and its receipts inside a block range.
32    async fn read_block_and_receipts_in_range(&self, start: BlockNumber, end: BlockNumber) -> anyhow::Result<Vec<ExternalBlockWithReceipts>>;
33
34    /// Read all initial accounts saved.
35    async fn read_initial_accounts(&self) -> anyhow::Result<Vec<Account>>;
36
37    /// Saves an initial account with its starting balance.
38    async fn save_initial_account(&self, address: Address, balance: Wei) -> anyhow::Result<()>;
39
40    /// Save an external block and its receipts to the storage.
41    async fn save_block_and_receipts(&self, number: BlockNumber, block: JsonValue, receipts: Vec<(Hash, ExternalReceipt)>) -> anyhow::Result<()>;
42}
43
44// -----------------------------------------------------------------------------
45// Config
46// -----------------------------------------------------------------------------
47
48/// External RPC storage configuration.
49#[derive(DebugAsJson, Clone, Parser, serde::Serialize)]
50pub struct ExternalRpcConfig {
51    /// External RPC storage implementation.
52    #[arg(long = "external-rpc-storage", env = "EXTERNAL_RPC_STORAGE")]
53    pub external_rpc_storage_kind: ExternalRpcKind,
54
55    /// External RPC storage number of parallel open connections.
56    #[arg(long = "external-rpc-storage-connections", env = "EXTERNAL_RPC_STORAGE_CONNECTIONS")]
57    pub external_rpc_storage_connections: u32,
58
59    /// External RPC storage timeout when opening a connection.
60    #[arg(long = "external-rpc-storage-timeout", value_parser=parse_duration, env = "EXTERNAL_RPC_STORAGE_TIMEOUT")]
61    pub external_rpc_storage_timeout: Duration,
62
63    /// External RPC threshold in seconds for warning slow queries.
64    #[arg(long = "external-rpc-slow-query-warn-threshold", value_parser=parse_duration, env = "EXTERNAL_RPC_SLOW_QUERY_WARN_THRESHOLD", default_value = "1s")]
65    pub external_rpc_slow_query_warn_threshold: Duration,
66}
67
68#[derive(DebugAsJson, Clone, serde::Serialize)]
69pub enum ExternalRpcKind {
70    Postgres { url: String },
71}
72
73impl ExternalRpcConfig {
74    /// Initializes external rpc storage implementation.
75    pub async fn init(&self) -> anyhow::Result<Arc<PostgresExternalRpc>> {
76        tracing::info!(config = ?self, "creating external rpc storage");
77
78        let ExternalRpcKind::Postgres { url } = &self.external_rpc_storage_kind;
79
80        let config = PostgresExternalRpcConfig {
81            url: url.to_owned(),
82            connections: self.external_rpc_storage_connections,
83            acquire_timeout: self.external_rpc_storage_timeout,
84            slow_query_warn_threshold: self.external_rpc_slow_query_warn_threshold,
85        };
86
87        Ok(Arc::new(PostgresExternalRpc::new(config).await?))
88    }
89}
90
91impl FromStr for ExternalRpcKind {
92    type Err = anyhow::Error;
93
94    fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
95        match s {
96            s if s.starts_with("postgres://") => Ok(Self::Postgres { url: s.to_string() }),
97            s => Err(anyhow!("unknown external rpc storage: {}", s)),
98        }
99    }
100}