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_helper::network::Network;
17use cuprate_rpc_interface::{RouterBuilder, RpcHandler};
18use cuprate_txpool::service::TxpoolReadHandle;
19
20use crate::{
21 config::{restricted_rpc_port, unrestricted_rpc_port, RpcConfig},
22 rpc::{rpc_handler::BlockchainManagerHandle, CupratedRpcHandler},
23 txpool::IncomingTxHandler,
24};
25
26pub fn init_rpc_servers(
34 config: RpcConfig,
35 network: Network,
36 blockchain_read: BlockchainReadHandle,
37 blockchain_context: BlockchainContextService,
38 txpool_read: TxpoolReadHandle,
39 tx_handler: IncomingTxHandler,
40) {
41 for ((enable, addr, port, request_byte_limit), restricted) in [
42 (
43 (
44 config.unrestricted.enable,
45 config.unrestricted.address,
46 unrestricted_rpc_port(config.unrestricted.port, network),
47 config.unrestricted.request_byte_limit,
48 ),
49 false,
50 ),
51 (
52 (
53 config.restricted.enable,
54 config.restricted.address,
55 restricted_rpc_port(config.restricted.port, network),
56 config.restricted.request_byte_limit,
57 ),
58 true,
59 ),
60 ] {
61 if !enable {
62 info!(restricted, "Skipping RPC server");
63 continue;
64 }
65
66 if !restricted && !cuprate_helper::net::ip_is_local(addr) {
67 if config
68 .unrestricted
69 .i_know_what_im_doing_allow_public_unrestricted_rpc
70 {
71 warn!(
72 address = %addr,
73 "Starting unrestricted RPC on non-local address, this is dangerous!"
74 );
75 } else {
76 panic!("Refusing to start unrestricted RPC on a non-local address ({addr})");
77 }
78 }
79
80 let rpc_handler = CupratedRpcHandler::new(
81 restricted,
82 blockchain_read.clone(),
83 blockchain_context.clone(),
84 txpool_read.clone(),
85 tx_handler.clone(),
86 );
87
88 tokio::task::spawn(async move {
89 run_rpc_server(
90 rpc_handler,
91 restricted,
92 SocketAddr::new(addr, port),
93 request_byte_limit,
94 )
95 .await
96 .unwrap();
97 });
98 }
99}
100
101async fn run_rpc_server(
105 rpc_handler: CupratedRpcHandler,
106 restricted: bool,
107 address: SocketAddr,
108 request_byte_limit: usize,
109) -> Result<(), Error> {
110 info!(
111 restricted,
112 address = %address,
113 "Starting RPC server"
114 );
115
116 let router = RouterBuilder::new()
120 .json_rpc()
121 .other_get_height()
122 .other_send_raw_transaction()
123 .other_sendrawtransaction()
124 .fallback()
125 .build()
126 .with_state(rpc_handler);
127
128 let router = if request_byte_limit != 0 {
132 router.layer(RequestBodyLimitLayer::new(request_byte_limit))
133 } else {
134 router
135 };
136
137 let listener = TcpListener::bind(address).await?;
141 axum::serve(listener, router).await?;
142
143 Ok(())
144}