From d68ba7e3f025482cb20ebc70cf1789c20d5a95d7 Mon Sep 17 00:00:00 2001 From: aniketfuryrocks Date: Sun, 22 Oct 2023 20:54:45 +0530 Subject: [PATCH 1/2] implement rpc methods with a todo!() clause --- Cargo.toml | 2 +- lite-rpc/src/bridge.rs | 256 ++++++++++++++++++++++++++----------- lite-rpc/src/rpc.rs | 194 ++++++++++++++++++++++++---- lite-rpc/src/rpc_tester.rs | 2 +- 4 files changed, 352 insertions(+), 102 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed1e2abc..6b1c0424 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,4 +61,4 @@ solana-lite-rpc-history = {path = "history", version="0.2.3"} async-trait = "0.1.68" yellowstone-grpc-client = "1.9.0" -yellowstone-grpc-proto = "1.9.0" \ No newline at end of file +yellowstone-grpc-proto = "1.9.0" diff --git a/lite-rpc/src/bridge.rs b/lite-rpc/src/bridge.rs index 6497d4ff..49a2f798 100644 --- a/lite-rpc/src/bridge.rs +++ b/lite-rpc/src/bridge.rs @@ -21,10 +21,16 @@ use solana_lite_rpc_history::history::History; use solana_rpc_client::nonblocking::rpc_client::RpcClient; use solana_rpc_client_api::{ config::{ - RpcBlockConfig, RpcContextConfig, RpcEncodingConfigWrapper, RpcRequestAirdropConfig, - RpcSignatureStatusConfig, + RpcBlockConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter, RpcBlocksConfigWrapper, + RpcContextConfig, RpcEncodingConfigWrapper, RpcEpochConfig, RpcGetVoteAccountsConfig, + RpcProgramAccountsConfig, RpcRequestAirdropConfig, RpcSignatureStatusConfig, + RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsFilter, RpcTransactionLogsConfig, + }, + response::{ + Response as RpcResponse, RpcBlockhash, RpcConfirmedTransactionStatusWithSignature, + RpcContactInfo, RpcLeaderSchedule, RpcPerfSample, RpcPrioritizationFee, RpcResponseContext, + RpcVersionInfo, RpcVoteAccountStatus, }, - response::{Response as RpcResponse, RpcBlockhash, RpcResponseContext, RpcVersionInfo}, }; use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey, slot_history::Slot}; use solana_transaction_status::{TransactionStatus, UiConfirmedBlock}; @@ -117,39 +123,68 @@ impl LiteBridge { #[jsonrpsee::core::async_trait] impl LiteRpcServer for LiteBridge { - async fn send_transaction( + async fn get_block( &self, - tx: String, - send_transaction_config: Option, - ) -> crate::rpc::Result { - RPC_SEND_TX.inc(); - - let SendTransactionConfig { - encoding, - max_retries, - } = send_transaction_config.unwrap_or_default(); - - let raw_tx = match encoding.decode(tx) { - Ok(raw_tx) => raw_tx, - Err(err) => { - return Err(jsonrpsee::core::Error::Custom(err.to_string())); - } - }; - - match self - .transaction_service - .send_transaction(raw_tx, max_retries) - .await - { - Ok(sig) => { - TXS_IN_CHANNEL.inc(); - - Ok(sig) - } - Err(e) => Err(jsonrpsee::core::Error::Custom(e.to_string())), + slot: u64, + config: Option>, + ) -> crate::rpc::Result> { + let config = config.map_or(RpcBlockConfig::default(), |x| x.convert_to_current()); + let block = self.history.block_storage.get(slot, config).await; + if block.is_ok() { + // TO DO Convert to UIConfirmed Block + Err(jsonrpsee::core::Error::HttpNotImplemented) + } else { + Ok(None) } } + async fn get_blocks( + &self, + _start_slot: Slot, + _config: Option, + _commitment: Option, + ) -> crate::rpc::Result> { + todo!() + } + + async fn get_signatures_for_address( + &self, + _address: String, + _config: Option, + ) -> crate::rpc::Result> { + todo!() + } + + async fn get_cluster_nodes(&self) -> crate::rpc::Result> { + todo!() + } + + + async fn get_slot(&self, config: Option) -> crate::rpc::Result { + let commitment_config = config + .map(|config| config.commitment.unwrap_or_default()) + .unwrap_or_default(); + + let BlockInformation { slot, .. } = self + .data_cache + .block_information_store + .get_latest_block(commitment_config) + .await; + Ok(slot) + } + + async fn get_block_height(&self, _config: Option) -> crate::rpc::Result { + todo!() + } + + async fn get_block_time(&self, _block: u64) -> crate::rpc::Result { + todo!() + } + + async fn get_first_available_block(&self) -> crate::rpc::Result { + todo!() + } + async fn get_latest_blockhash( &self, config: Option, @@ -210,6 +245,50 @@ impl LiteRpcServer for LiteBridge { }) } + async fn get_epoch_info( + &self, + config: Option, + ) -> crate::rpc::Result { + let commitment_config = config + .map(|config| config.commitment.unwrap_or_default()) + .unwrap_or_default(); + let block_info = self + .data_cache + .block_information_store + .get_latest_block_info(commitment_config) + .await; + + //TODO manage transaction_count of epoch info. Currently None. + let epoch_info = self + .data_cache + .get_current_epoch(commitment_config) + .await + .into_epoch_info(block_info.block_height, None); + Ok(epoch_info) + } + + async fn get_leader_schedule( + &self, + _slot: Option, + _config: Option>, + ) -> crate::rpc::Result> { + todo!() + } + + async fn get_vote_accounts( + &self, + _config: Option, + ) -> crate::rpc::Result { + todo!() + } + + async fn get_recent_performance_samples( + &self, + _limit: Option, + ) -> crate::rpc::Result> { + todo!() + } + async fn get_signature_statuses( &self, sigs: Vec, @@ -236,6 +315,46 @@ impl LiteRpcServer for LiteBridge { }) } + async fn get_recent_prioritization_fees( + &self, + _pubkey_strs: Option>, + ) -> crate::rpc::Result> { + todo!() + } + + async fn send_transaction( + &self, + tx: String, + send_transaction_config: Option, + ) -> crate::rpc::Result { + RPC_SEND_TX.inc(); + + let SendTransactionConfig { + encoding, + max_retries, + } = send_transaction_config.unwrap_or_default(); + + let raw_tx = match encoding.decode(tx) { + Ok(raw_tx) => raw_tx, + Err(err) => { + return Err(jsonrpsee::core::Error::Custom(err.to_string())); + } + }; + + match self + .transaction_service + .send_transaction(raw_tx, max_retries) + .await + { + Ok(sig) => { + TXS_IN_CHANNEL.inc(); + + Ok(sig) + } + Err(e) => Err(jsonrpsee::core::Error::Custom(e.to_string())), + } + } + fn get_version(&self) -> crate::rpc::Result { RPC_GET_VERSION.inc(); @@ -290,24 +409,33 @@ impl LiteRpcServer for LiteBridge { Ok(airdrop_sig) } - async fn get_slot(&self, config: Option) -> crate::rpc::Result { - let commitment_config = config - .map(|config| config.commitment.unwrap_or_default()) - .unwrap_or_default(); + async fn program_subscribe( + &self, _pending: PendingSubscriptionSink, + _pubkey_str: String, + _config: Option, + ) -> SubscriptionResult { todo!() } - let BlockInformation { slot, .. } = self - .data_cache - .block_information_store - .get_latest_block(commitment_config) - .await; - Ok(slot) - } + async fn slot_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { todo!() } + async fn block_subscribe( + &self, _pending: PendingSubscriptionSink, + _filter: RpcBlockSubscribeFilter, + _config: Option, + ) -> SubscriptionResult { todo!() } + + + async fn logs_subscribe( + &self, _pending: PendingSubscriptionSink, + _filter: RpcTransactionLogsFilter, + _config: Option, + ) -> SubscriptionResult { todo!() } + + // WARN: enable_received_notification: bool is ignored async fn signature_subscribe( &self, pending: PendingSubscriptionSink, signature: String, - commitment_config: CommitmentConfig, + config: RpcSignatureSubscribeConfig, ) -> SubscriptionResult { RPC_SIGNATURE_SUBSCRIBE.inc(); let sink = pending.accept().await?; @@ -315,47 +443,19 @@ impl LiteRpcServer for LiteBridge { let jsonrpsee_sink = JsonRpseeSubscriptionHandlerSink::new(sink); self.data_cache.tx_subs.signature_subscribe( signature, - commitment_config, + config.commitment.unwrap_or_default(), Arc::new(jsonrpsee_sink), ); Ok(()) } - async fn get_block( - &self, - slot: u64, - config: Option>, - ) -> crate::rpc::Result> { - let config = config.map_or(RpcBlockConfig::default(), |x| x.convert_to_current()); - let block = self.history.block_storage.get(slot, config).await; - if block.is_ok() { - // TO DO Convert to UIConfirmed Block - Err(jsonrpsee::core::Error::HttpNotImplemented) - } else { - Ok(None) - } + async fn slot_updates_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { + todo!() } - async fn get_epoch_info( - &self, - config: Option, - ) -> crate::rpc::Result { - let commitment_config = config - .map(|config| config.commitment.unwrap_or_default()) - .unwrap_or_default(); - let block_info = self - .data_cache - .block_information_store - .get_latest_block_info(commitment_config) - .await; - - //TODO manage transaction_count of epoch info. Currently None. - let epoch_info = self - .data_cache - .get_current_epoch(commitment_config) - .await - .into_epoch_info(block_info.block_height, None); - Ok(epoch_info) + async fn vote_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { + todo!() } + } diff --git a/lite-rpc/src/rpc.rs b/lite-rpc/src/rpc.rs index 5d725ac4..512286f7 100644 --- a/lite-rpc/src/rpc.rs +++ b/lite-rpc/src/rpc.rs @@ -1,10 +1,17 @@ use jsonrpsee::core::SubscriptionResult; use jsonrpsee::proc_macros::rpc; use solana_rpc_client_api::config::{ - RpcBlockConfig, RpcContextConfig, RpcEncodingConfigWrapper, RpcRequestAirdropConfig, - RpcSignatureStatusConfig, + RpcBlockConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter, RpcBlocksConfigWrapper, + RpcContextConfig, RpcEncodingConfigWrapper, RpcEpochConfig, RpcGetVoteAccountsConfig, + RpcProgramAccountsConfig, RpcRequestAirdropConfig, RpcSignatureStatusConfig, + RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsFilter, RpcTransactionLogsConfig, }; -use solana_rpc_client_api::response::{Response as RpcResponse, RpcBlockhash, RpcVersionInfo}; +use solana_rpc_client_api::response::{ + Response as RpcResponse, RpcBlockhash, RpcConfirmedTransactionStatusWithSignature, + RpcContactInfo, RpcLeaderSchedule, RpcPerfSample, RpcPrioritizationFee, RpcVersionInfo, + RpcVoteAccountStatus, +}; + use solana_sdk::commitment_config::CommitmentConfig; use solana_sdk::epoch_info::EpochInfo; use solana_sdk::slot_history::Slot; @@ -16,12 +23,63 @@ pub type Result = std::result::Result; #[rpc(server)] pub trait LiteRpc { - #[method(name = "sendTransaction")] - async fn send_transaction( + // *********************** + // History Domain + // *********************** + + #[method(name = "getBlock")] + async fn get_block( &self, - tx: String, - send_transaction_config: Option, - ) -> Result; + slot: u64, + config: Option>, + ) -> Result>; + + #[method(name = "getBlocks")] + async fn get_blocks( + &self, + start_slot: Slot, + config: Option, + commitment: Option, + ) -> Result>; + + #[method(name = "getSignaturesForAddress")] + async fn get_signatures_for_address( + &self, + address: String, + config: Option, + ) -> Result>; + + // issue: solana_transaction_status::EncodedConfirmedTransactionWithStatusMeta does not implement Clone + // + //#[method(name = "getTransaction")] + //async fn get_transaction( + // &self, + // signature_str: String, + // config: Option>, + //) -> Result>; + + // *********************** + // Cluster Domain + // *********************** + + #[method(name = "getClusterNodes")] + async fn get_cluster_nodes(&self) -> Result>; + + // *********************** + // Validator Domain + // *********************** + + #[method(name = "getSlot")] + async fn get_slot(&self, config: Option) -> Result; + + #[method(name = "getBlockHeight")] + async fn get_block_height(&self, config: Option) -> Result; + + #[method(name = "getBlockTime")] + async fn get_block_time(&self, block: u64) -> Result; + + #[method(name = "getFirstAvailableBlock")] + async fn get_first_available_block(&self) -> Result; #[method(name = "getLatestBlockhash")] async fn get_latest_blockhash( @@ -36,6 +94,44 @@ pub trait LiteRpc { config: Option, ) -> Result>; + // BlockCommitmentArray is defined in solana/runtime/src/commitment.rs + // + // pub type BlockCommitmentArray = [u64; MAX_LOCKOUT_HISTORY + 1]; + // + // where + // solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY, + // + // Maximum number of votes to keep around, tightly coupled with epoch_schedule::MINIMUM_SLOTS_PER_EPOCH + // pub const MAX_LOCKOUT_HISTORY: usize = 31; + // + // #[method(name = "getBlockCommitment")] + // async fn get_block_commitment( + // &self, + // block: u64, + // ) -> Result>; + + #[method(name = "getEpochInfo")] + async fn get_epoch_info(&self, config: Option) -> Result; + + #[method(name = "getLeaderSchedule")] + async fn get_leader_schedule( + &self, + slot: Option, + config: Option>, + ) -> Result>; + + #[method(name = "getVoteAccounts")] + async fn get_vote_accounts( + &self, + config: Option, + ) -> Result; + + #[method(name = "getRecentPerformanceSamples")] + async fn get_recent_performance_samples( + &self, + limit: Option, + ) -> Result>; + #[method(name = "getSignatureStatuses")] async fn get_signature_statuses( &self, @@ -43,6 +139,27 @@ pub trait LiteRpc { config: Option, ) -> Result>>>; + #[method(name = "getRecentPrioritizationFees")] + async fn get_recent_prioritization_fees( + &self, + pubkey_strs: Option>, + ) -> Result>; + + // *********************** + // Send Transaction Domain + // *********************** + + #[method(name = "sendTransaction")] + async fn send_transaction( + &self, + tx: String, + send_transaction_config: Option, + ) -> Result; + + // *********************** + // Deprecated + // *********************** + #[method(name = "getVersion")] fn get_version(&self) -> Result; @@ -54,26 +171,59 @@ pub trait LiteRpc { config: Option, ) -> Result; - #[method(name = "getSlot")] - async fn get_slot(&self, config: Option) -> Result; + // *********************** + // Direct Subscription Domain + // *********************** + #[subscription(name = "programSubscribe" => "programNotification", unsubscribe="programUnsubscribe", item=RpcResponse)] + async fn program_subscribe( + &self, + pubkey_str: String, + config: Option, + ) -> SubscriptionResult; + + #[subscription(name = "slotSubscribe" => "slotNotification", unsubscribe="slotUnsubscribe", item=Slot)] + async fn slot_subscribe(&self) -> SubscriptionResult; + + #[subscription(name = "blockSubscribe" => "blockNotification", unsubscribe="blockUnsubscribe", item=RpcResponse)] + async fn block_subscribe( + &self, + filter: RpcBlockSubscribeFilter, + config: Option, + ) -> SubscriptionResult; + + // [transactionSubscribe](https://github.com/solana-foundation/solana-improvement-documents/pull/69) + // + //#[subscription(name = "transactionSubscribe" => "transactionNotification", unsubscribe="transactionUnsubscribe", item=RpcResponse)] + //async fn transaction_subscribe( + // &self, + // commitment_config: CommitmentConfig, + //) -> SubscriptionResult; + + // *********************** + // Indirect Subscription Domain + // *********************** + + #[subscription(name = "logsSubscribe" => "logsNotification", unsubscribe="logsUnsubscribe", item=RpcResponse)] + async fn logs_subscribe( + &self, + filter: RpcTransactionLogsFilter, + config: Option, + ) -> SubscriptionResult; + + // WARN: enable_received_notification: bool is ignored #[subscription(name = "signatureSubscribe" => "signatureNotification", unsubscribe="signatureUnsubscribe", item=RpcResponse)] async fn signature_subscribe( &self, signature: String, - commitment_config: CommitmentConfig, + config: RpcSignatureSubscribeConfig, ) -> SubscriptionResult; - #[method(name = "getBlock")] - async fn get_block( - &self, - slot: u64, - config: Option>, - ) -> Result>; + #[subscription(name = "slotUpdatesSubscribe" => "slotUpdatesNotification", unsubscribe="slotUpdatesUnsubscribe", item=SlotUpdate)] + async fn slot_updates_subscribe(&self) -> SubscriptionResult; + + + #[subscription(name = "voteSubscribe" => "voteNotification", unsubscribe="voteUnsubscribe", item=RpcVote)] + async fn vote_subscribe(&self) -> SubscriptionResult; - #[method(name = "getEpochInfo")] - async fn get_epoch_info( - &self, - config: Option, - ) -> crate::rpc::Result; } diff --git a/lite-rpc/src/rpc_tester.rs b/lite-rpc/src/rpc_tester.rs index e5729d6a..bdf50234 100644 --- a/lite-rpc/src/rpc_tester.rs +++ b/lite-rpc/src/rpc_tester.rs @@ -27,7 +27,7 @@ impl RpcTester { // sleep for 5 seconds tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; // do a simple request to self for getVersion - let Err(err) = rpc_client.get_version().await else { + let Err(err) = rpc_client.get_slot().await else { RPC_RESPONDING.set(1.0); continue; }; From b7c9c7e55f202392e4fa4c934c831f4d94e8c958 Mon Sep 17 00:00:00 2001 From: aniketfuryrocks Date: Sun, 22 Oct 2023 21:09:41 +0530 Subject: [PATCH 2/2] fmt --- lite-rpc/src/bridge.rs | 42 +++++++++++++++++++++++++++--------------- lite-rpc/src/rpc.rs | 5 ++--- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/lite-rpc/src/bridge.rs b/lite-rpc/src/bridge.rs index 49a2f798..9e785f4b 100644 --- a/lite-rpc/src/bridge.rs +++ b/lite-rpc/src/bridge.rs @@ -21,10 +21,11 @@ use solana_lite_rpc_history::history::History; use solana_rpc_client::nonblocking::rpc_client::RpcClient; use solana_rpc_client_api::{ config::{ - RpcBlockConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter, RpcBlocksConfigWrapper, - RpcContextConfig, RpcEncodingConfigWrapper, RpcEpochConfig, RpcGetVoteAccountsConfig, - RpcProgramAccountsConfig, RpcRequestAirdropConfig, RpcSignatureStatusConfig, - RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsFilter, RpcTransactionLogsConfig, + RpcBlockConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter, RpcBlocksConfigWrapper, + RpcContextConfig, RpcEncodingConfigWrapper, RpcEpochConfig, RpcGetVoteAccountsConfig, + RpcProgramAccountsConfig, RpcRequestAirdropConfig, RpcSignatureStatusConfig, + RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsConfig, + RpcTransactionLogsFilter, }, response::{ Response as RpcResponse, RpcBlockhash, RpcConfirmedTransactionStatusWithSignature, @@ -159,7 +160,6 @@ impl LiteRpcServer for LiteBridge { todo!() } - async fn get_slot(&self, config: Option) -> crate::rpc::Result { let commitment_config = config .map(|config| config.commitment.unwrap_or_default()) @@ -410,25 +410,35 @@ impl LiteRpcServer for LiteBridge { } async fn program_subscribe( - &self, _pending: PendingSubscriptionSink, + &self, + _pending: PendingSubscriptionSink, _pubkey_str: String, _config: Option, - ) -> SubscriptionResult { todo!() } + ) -> SubscriptionResult { + todo!() + } - async fn slot_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { todo!() } + async fn slot_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { + todo!() + } async fn block_subscribe( - &self, _pending: PendingSubscriptionSink, + &self, + _pending: PendingSubscriptionSink, _filter: RpcBlockSubscribeFilter, _config: Option, - ) -> SubscriptionResult { todo!() } - + ) -> SubscriptionResult { + todo!() + } async fn logs_subscribe( - &self, _pending: PendingSubscriptionSink, + &self, + _pending: PendingSubscriptionSink, _filter: RpcTransactionLogsFilter, _config: Option, - ) -> SubscriptionResult { todo!() } + ) -> SubscriptionResult { + todo!() + } // WARN: enable_received_notification: bool is ignored async fn signature_subscribe( @@ -450,12 +460,14 @@ impl LiteRpcServer for LiteBridge { Ok(()) } - async fn slot_updates_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { + async fn slot_updates_subscribe( + &self, + _pending: PendingSubscriptionSink, + ) -> SubscriptionResult { todo!() } async fn vote_subscribe(&self, _pending: PendingSubscriptionSink) -> SubscriptionResult { todo!() } - } diff --git a/lite-rpc/src/rpc.rs b/lite-rpc/src/rpc.rs index 512286f7..3164a1bf 100644 --- a/lite-rpc/src/rpc.rs +++ b/lite-rpc/src/rpc.rs @@ -4,7 +4,8 @@ use solana_rpc_client_api::config::{ RpcBlockConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter, RpcBlocksConfigWrapper, RpcContextConfig, RpcEncodingConfigWrapper, RpcEpochConfig, RpcGetVoteAccountsConfig, RpcProgramAccountsConfig, RpcRequestAirdropConfig, RpcSignatureStatusConfig, - RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsFilter, RpcTransactionLogsConfig, + RpcSignatureSubscribeConfig, RpcSignaturesForAddressConfig, RpcTransactionLogsConfig, + RpcTransactionLogsFilter, }; use solana_rpc_client_api::response::{ Response as RpcResponse, RpcBlockhash, RpcConfirmedTransactionStatusWithSignature, @@ -222,8 +223,6 @@ pub trait LiteRpc { #[subscription(name = "slotUpdatesSubscribe" => "slotUpdatesNotification", unsubscribe="slotUpdatesUnsubscribe", item=SlotUpdate)] async fn slot_updates_subscribe(&self) -> SubscriptionResult; - #[subscription(name = "voteSubscribe" => "voteNotification", unsubscribe="voteUnsubscribe", item=RpcVote)] async fn vote_subscribe(&self) -> SubscriptionResult; - }