cuprated/rpc/
server.rs
1use std::{
4 net::{IpAddr, SocketAddr},
5 time::Duration,
6};
7
8use anyhow::Error;
9use tokio::net::TcpListener;
10use tower::limit::rate::RateLimitLayer;
11use tower_http::limit::RequestBodyLimitLayer;
12use tracing::{info, warn};
13
14use cuprate_blockchain::service::BlockchainReadHandle;
15use cuprate_consensus::BlockchainContextService;
16use cuprate_rpc_interface::{RouterBuilder, RpcHandler};
17use cuprate_txpool::service::TxpoolReadHandle;
18
19use crate::{
20 config::RpcConfig,
21 rpc::{rpc_handler::BlockchainManagerHandle, CupratedRpcHandler},
22};
23
24pub fn init_rpc_servers(
32 config: RpcConfig,
33 blockchain_read: BlockchainReadHandle,
34 blockchain_context: BlockchainContextService,
35 txpool_read: TxpoolReadHandle,
36) {
37 for ((enable, addr, request_byte_limit), restricted) in [
38 (
39 (
40 config.unrestricted.enable,
41 config.unrestricted.address,
42 config.unrestricted.request_byte_limit,
43 ),
44 false,
45 ),
46 (
47 (
48 config.restricted.enable,
49 config.restricted.address,
50 config.restricted.request_byte_limit,
51 ),
52 true,
53 ),
54 ] {
55 if !enable {
56 info!(restricted, "Skipping RPC server");
57 continue;
58 }
59
60 if !restricted && !cuprate_helper::net::ip_is_local(addr.ip()) {
61 if config
62 .unrestricted
63 .i_know_what_im_doing_allow_public_unrestricted_rpc
64 {
65 warn!(
66 address = %addr,
67 "Starting unrestricted RPC on non-local address, this is dangerous!"
68 );
69 } else {
70 panic!("Refusing to start unrestricted RPC on a non-local address ({addr})");
71 }
72 }
73
74 let rpc_handler = CupratedRpcHandler::new(
75 restricted,
76 blockchain_read.clone(),
77 blockchain_context.clone(),
78 txpool_read.clone(),
79 );
80
81 tokio::task::spawn(async move {
82 run_rpc_server(rpc_handler, restricted, addr, request_byte_limit)
83 .await
84 .unwrap();
85 });
86 }
87}
88
89async fn run_rpc_server(
93 rpc_handler: CupratedRpcHandler,
94 restricted: bool,
95 address: SocketAddr,
96 request_byte_limit: usize,
97) -> Result<(), Error> {
98 info!(
99 restricted,
100 address = %address,
101 "Starting RPC server"
102 );
103
104 let router = RouterBuilder::new()
108 .json_rpc()
109 .other_get_height()
110 .fallback()
111 .build()
112 .with_state(rpc_handler);
113
114 let router = if request_byte_limit != 0 {
118 router.layer(RequestBodyLimitLayer::new(request_byte_limit))
119 } else {
120 router
121 };
122
123 let listener = TcpListener::bind(address).await?;
127 axum::serve(listener, router).await?;
128
129 Ok(())
130}