lite-rpc/src/bridge.rs

346 lines
10 KiB
Rust
Raw Normal View History

2022-12-16 18:35:49 -08:00
use crate::{
2023-01-11 21:35:09 -08:00
configs::{IsBlockHashValidConfig, SendTransactionConfig},
2022-12-16 18:35:49 -08:00
encoding::BinaryEncoding,
2023-01-27 12:35:29 -08:00
postgres::Postgres,
2023-01-04 02:58:25 -08:00
rpc::LiteRpcServer,
2023-01-16 23:06:00 -08:00
tpu_manager::TpuManager,
2023-01-27 12:35:29 -08:00
workers::{BlockListener, Cleaner, MetricsCapture, TxSender},
2022-12-16 18:35:49 -08:00
};
2023-01-09 22:40:43 -08:00
use std::{ops::Deref, str::FromStr, sync::Arc, time::Duration};
2022-12-16 18:35:49 -08:00
2023-01-04 02:58:25 -08:00
use anyhow::bail;
2023-01-07 04:40:56 -08:00
2023-01-05 02:54:00 -08:00
use log::info;
2022-12-16 18:35:49 -08:00
2023-01-04 05:21:00 -08:00
use jsonrpsee::{server::ServerBuilder, types::SubscriptionResult, SubscriptionSink};
2022-12-16 18:35:49 -08:00
use solana_client::{
2023-01-16 23:05:24 -08:00
nonblocking::{pubsub_client::PubsubClient, rpc_client::RpcClient},
2023-01-12 05:55:04 -08:00
rpc_client::SerializableTransaction,
2023-01-04 03:11:37 -08:00
rpc_config::{RpcContextConfig, RpcRequestAirdropConfig},
2023-01-04 02:58:25 -08:00
rpc_response::{Response as RpcResponse, RpcBlockhash, RpcResponseContext, RpcVersionInfo},
};
use solana_sdk::{
commitment_config::{CommitmentConfig, CommitmentLevel},
2023-01-11 21:35:09 -08:00
hash::Hash,
2023-01-04 03:11:37 -08:00
pubkey::Pubkey,
2023-01-04 02:58:25 -08:00
transaction::VersionedTransaction,
2022-12-27 02:11:06 -08:00
};
use solana_transaction_status::TransactionStatus;
2023-01-04 02:58:25 -08:00
use tokio::{net::ToSocketAddrs, task::JoinHandle};
2022-12-16 18:35:49 -08:00
/// A bridge between clients and tpu
2022-12-18 07:09:37 -08:00
pub struct LiteBridge {
2023-01-16 23:05:24 -08:00
pub rpc_client: Arc<RpcClient>,
pub tpu_manager: Arc<TpuManager>,
2023-01-09 22:40:43 -08:00
pub tx_sender: TxSender,
2023-01-04 02:58:25 -08:00
pub finalized_block_listenser: BlockListener,
pub confirmed_block_listenser: BlockListener,
2022-12-16 18:35:49 -08:00
}
2022-12-18 07:09:37 -08:00
impl LiteBridge {
2023-01-16 23:05:24 -08:00
pub async fn new(rpc_url: String, ws_addr: String, fanout_slots: u64) -> anyhow::Result<Self> {
2023-01-11 21:35:09 -08:00
let rpc_client = Arc::new(RpcClient::new(rpc_url.clone()));
2022-12-16 18:35:49 -08:00
2023-01-16 23:05:24 -08:00
let pub_sub_client = Arc::new(PubsubClient::new(&ws_addr).await?);
2022-12-16 18:35:49 -08:00
2023-01-16 23:05:24 -08:00
let tpu_manager =
Arc::new(TpuManager::new(rpc_client.clone(), ws_addr, fanout_slots).await?);
2023-01-09 23:06:24 -08:00
2023-01-16 23:05:24 -08:00
let tx_sender = TxSender::new(tpu_manager.clone());
2023-01-08 06:13:33 -08:00
let finalized_block_listenser = BlockListener::new(
pub_sub_client.clone(),
rpc_client.clone(),
2023-01-10 06:56:41 -08:00
tx_sender.clone(),
2023-01-08 06:13:33 -08:00
CommitmentConfig::finalized(),
)
.await?;
let confirmed_block_listenser = BlockListener::new(
pub_sub_client,
rpc_client.clone(),
2023-01-10 06:56:41 -08:00
tx_sender.clone(),
2023-01-08 06:13:33 -08:00
CommitmentConfig::confirmed(),
)
.await?;
2022-12-16 18:35:49 -08:00
Ok(Self {
2023-01-16 23:05:24 -08:00
rpc_client,
tpu_manager,
2023-01-09 22:40:43 -08:00
tx_sender,
2023-01-04 02:58:25 -08:00
finalized_block_listenser,
confirmed_block_listenser,
2022-12-16 18:35:49 -08:00
})
}
2023-01-04 02:58:25 -08:00
pub fn get_block_listner(&self, commitment_config: CommitmentConfig) -> BlockListener {
if let CommitmentLevel::Finalized = commitment_config.commitment {
self.finalized_block_listenser.clone()
} else {
self.confirmed_block_listenser.clone()
}
}
/// List for `JsonRpc` requests
2023-01-05 02:54:00 -08:00
pub async fn start_services<T: ToSocketAddrs + std::fmt::Debug + 'static + Send + Clone>(
2023-01-04 02:58:25 -08:00
self,
2023-01-05 02:54:00 -08:00
http_addr: T,
ws_addr: T,
2023-01-09 22:40:43 -08:00
tx_batch_size: usize,
tx_send_interval: Duration,
2023-01-10 06:56:41 -08:00
clean_interval: Duration,
2023-01-17 08:56:17 -08:00
postgres_config: &str,
) -> anyhow::Result<[JoinHandle<anyhow::Result<()>>; 8]> {
2023-01-09 22:40:43 -08:00
let tx_sender = self
.tx_sender
.clone()
.execute(tx_batch_size, tx_send_interval);
2023-01-27 12:35:29 -08:00
let metrics_capture = MetricsCapture::new(self.tx_sender.clone());
let (postgres_connection, postgres) = Postgres::new(postgres_config).await?;
let finalized_block_listenser = self
.finalized_block_listenser
.clone()
.listen(Some(postgres.clone()));
let confirmed_block_listenser = self
.confirmed_block_listenser
.clone()
.listen(Some(postgres.clone()));
2023-01-17 08:56:17 -08:00
2023-01-10 06:56:41 -08:00
let cleaner = Cleaner::new(
self.tx_sender.clone(),
[
self.finalized_block_listenser.clone(),
self.confirmed_block_listenser.clone(),
],
)
.start(clean_interval);
2023-01-09 22:40:43 -08:00
2023-01-27 12:35:29 -08:00
let rpc = self.into_rpc();
let (ws_server, http_server) = {
let ws_server_handle = ServerBuilder::default()
.ws_only()
.build(ws_addr.clone())
.await?
.start(rpc.clone())?;
let http_server_handle = ServerBuilder::default()
.http_only()
.build(http_addr.clone())
.await?
.start(rpc)?;
let ws_server = tokio::spawn(async move {
info!("Websocket Server started at {ws_addr:?}");
ws_server_handle.stopped().await;
bail!("Websocket server stopped");
});
let http_server = tokio::spawn(async move {
info!("HTTP Server started at {http_addr:?}");
http_server_handle.stopped().await;
bail!("HTTP server stopped");
});
(ws_server, http_server)
};
2023-01-10 06:56:41 -08:00
Ok([
2023-01-05 02:54:00 -08:00
ws_server,
http_server,
2023-01-09 22:40:43 -08:00
tx_sender,
2023-01-05 02:54:00 -08:00
finalized_block_listenser,
confirmed_block_listenser,
2023-01-27 12:35:29 -08:00
postgres_connection,
metrics_capture.capture(Some(postgres)),
2023-01-10 06:56:41 -08:00
cleaner,
2023-01-09 22:40:43 -08:00
])
2023-01-04 02:58:25 -08:00
}
}
#[jsonrpsee::core::async_trait]
impl LiteRpcServer for LiteBridge {
async fn send_transaction(
2022-12-16 18:35:49 -08:00
&self,
2023-01-03 01:50:09 -08:00
tx: String,
2023-01-04 04:13:23 -08:00
send_transaction_config: Option<SendTransactionConfig>,
) -> crate::rpc::Result<String> {
let SendTransactionConfig {
2023-01-03 01:50:09 -08:00
encoding,
max_retries: _,
2023-01-04 04:13:23 -08:00
} = send_transaction_config.unwrap_or_default();
2023-01-12 05:55:04 -08:00
let raw_tx = match encoding.decode(tx) {
Ok(raw_tx) => raw_tx,
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
let tx = match bincode::deserialize::<VersionedTransaction>(&raw_tx) {
Ok(tx) => tx,
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
2022-12-16 18:35:49 -08:00
2023-01-12 05:55:04 -08:00
let sig = tx.get_signature();
2022-12-16 18:35:49 -08:00
2023-01-12 04:28:59 -08:00
self.tx_sender.enqnueue_tx(sig.to_string(), raw_tx).await;
2022-12-16 18:35:49 -08:00
Ok(BinaryEncoding::Base58.encode(sig))
}
2023-01-04 02:58:25 -08:00
async fn get_latest_blockhash(
&self,
config: Option<solana_client::rpc_config::RpcContextConfig>,
) -> crate::rpc::Result<RpcResponse<solana_client::rpc_response::RpcBlockhash>> {
let commitment_config = if let Some(RpcContextConfig { commitment, .. }) = config {
commitment.unwrap_or_default()
} else {
CommitmentConfig::default()
};
let block_listner = self.get_block_listner(commitment_config);
let (blockhash, last_valid_block_height) = block_listner.get_latest_blockhash().await;
2023-01-04 08:18:27 -08:00
let slot = block_listner.get_slot().await;
2023-01-04 02:58:25 -08:00
Ok(RpcResponse {
context: RpcResponseContext {
slot,
api_version: None,
},
value: RpcBlockhash {
blockhash,
last_valid_block_height,
},
})
}
2023-01-11 21:35:09 -08:00
async fn is_blockhash_valid(
&self,
blockhash: String,
config: Option<IsBlockHashValidConfig>,
) -> crate::rpc::Result<RpcResponse<bool>> {
let commitment = config.unwrap_or_default().commitment.unwrap_or_default();
let commitment = CommitmentConfig { commitment };
2023-01-12 05:55:04 -08:00
let blockhash = match Hash::from_str(&blockhash) {
Ok(blockhash) => blockhash,
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
2023-01-11 21:35:09 -08:00
let block_listner = self.get_block_listner(commitment);
2023-01-12 05:55:04 -08:00
let is_valid = match self
2023-01-16 23:05:24 -08:00
.rpc_client
2023-01-11 21:35:09 -08:00
.is_blockhash_valid(&blockhash, commitment)
.await
2023-01-12 05:55:04 -08:00
{
Ok(is_valid) => is_valid,
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
2023-01-11 21:35:09 -08:00
let slot = block_listner.get_slot().await;
Ok(RpcResponse {
context: RpcResponseContext {
slot,
api_version: None,
},
value: is_valid,
})
}
2023-01-04 02:58:25 -08:00
async fn get_signature_statuses(
2023-01-02 03:44:07 -08:00
&self,
2023-01-03 01:50:09 -08:00
sigs: Vec<String>,
2023-01-04 02:58:25 -08:00
_config: Option<solana_client::rpc_config::RpcSignatureStatusConfig>,
) -> crate::rpc::Result<RpcResponse<Vec<Option<TransactionStatus>>>> {
let sig_statuses = sigs
.iter()
2023-01-10 06:56:41 -08:00
.map(|sig| {
self.tx_sender
.txs_sent
.get(sig)
.and_then(|v| v.status.clone())
})
.collect();
2023-01-04 02:58:25 -08:00
2023-01-02 03:44:07 -08:00
Ok(RpcResponse {
context: RpcResponseContext {
2023-01-04 08:18:27 -08:00
slot: self.finalized_block_listenser.get_slot().await,
2023-01-02 03:44:07 -08:00
api_version: None,
},
2023-01-04 02:58:25 -08:00
value: sig_statuses,
2023-01-02 03:44:07 -08:00
})
2022-12-16 18:35:49 -08:00
}
2023-01-04 02:58:25 -08:00
fn get_version(&self) -> crate::rpc::Result<RpcVersionInfo> {
2022-12-16 18:35:49 -08:00
let version = solana_version::Version::default();
2023-01-04 02:58:25 -08:00
Ok(RpcVersionInfo {
2022-12-16 18:35:49 -08:00
solana_core: version.to_string(),
feature_set: Some(version.feature_set),
2023-01-04 02:58:25 -08:00
})
2022-12-16 18:35:49 -08:00
}
2023-01-04 03:11:37 -08:00
async fn request_airdrop(
&self,
pubkey_str: String,
lamports: u64,
2023-01-04 04:13:23 -08:00
config: Option<RpcRequestAirdropConfig>,
2023-01-04 03:11:37 -08:00
) -> crate::rpc::Result<String> {
2023-01-12 05:55:04 -08:00
let pubkey = match Pubkey::from_str(&pubkey_str) {
Ok(pubkey) => pubkey,
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
2023-01-04 03:11:37 -08:00
2023-01-12 05:55:04 -08:00
let airdrop_sig = match self
2023-01-16 23:05:24 -08:00
.rpc_client
2023-01-04 04:13:23 -08:00
.request_airdrop_with_config(&pubkey, lamports, config.unwrap_or_default())
2023-01-04 03:11:37 -08:00
.await
2023-01-12 05:55:04 -08:00
{
Ok(airdrop_sig) => airdrop_sig.to_string(),
Err(err) => {
return Err(jsonrpsee::core::Error::Custom(err.to_string()));
}
};
2023-01-08 06:28:14 -08:00
2023-01-10 06:56:41 -08:00
self.tx_sender
.txs_sent
.insert(airdrop_sig.clone(), Default::default());
2023-01-08 06:28:14 -08:00
Ok(airdrop_sig)
2023-01-04 03:11:37 -08:00
}
2023-01-04 05:21:00 -08:00
fn signature_subscribe(
&self,
2023-01-05 02:54:00 -08:00
mut sink: SubscriptionSink,
2023-01-04 05:21:00 -08:00
signature: String,
commitment_config: CommitmentConfig,
) -> SubscriptionResult {
2023-01-05 02:54:00 -08:00
sink.accept()?;
2023-01-04 05:21:00 -08:00
self.get_block_listner(commitment_config)
.signature_subscribe(signature, sink);
Ok(())
}
2022-12-16 18:35:49 -08:00
}
2022-12-23 11:58:42 -08:00
impl Deref for LiteBridge {
type Target = RpcClient;
fn deref(&self) -> &Self::Target {
2023-01-16 23:05:24 -08:00
&self.rpc_client
2022-12-23 11:58:42 -08:00
}
}