Split up solana-client (#27246)

* Move thin-client to new crate

* Move tpu client and varieties to new crate

* Move pubsub-client to new crate

* Move rpc-client to new crate

* Add client-common crate to avoid circular dependencies

* Move rpc_cache and make less pub

* Remove unused unpub modules

* Add nonce-client

* Remove unused dependencies

* Fix rpc_client docs

* Move spinner to calling clients

* Rename client-common to rpc-client-api

* Remove unnecessary rpc_ prefix

* Remove unused ClientErrorKind variant

* Remove unnecessary Client prefix

* Move mod declarations into lib.rs and remove unnecessary files

* Rename nonce-client and remove redundant module name

* Restore mock_sender_for_cli in solana-client
This commit is contained in:
Tyera Eulberg 2022-08-23 22:34:35 -07:00 committed by GitHub
parent efa6201eda
commit c24eaa36f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 1703 additions and 1450 deletions

196
Cargo.lock generated
View File

@ -4884,6 +4884,7 @@ dependencies = [
"solana-logger 1.12.0", "solana-logger 1.12.0",
"solana-program-runtime", "solana-program-runtime",
"solana-remote-wallet", "solana-remote-wallet",
"solana-rpc-client",
"solana-sdk 1.12.0", "solana-sdk 1.12.0",
"solana-streamer", "solana-streamer",
"solana-test-validator", "solana-test-validator",
@ -4942,58 +4943,15 @@ dependencies = [
name = "solana-client" name = "solana-client"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"anyhow",
"assert_matches",
"async-mutex",
"async-trait",
"base64 0.13.0",
"bincode",
"bs58",
"bytes",
"clap 2.33.3",
"crossbeam-channel",
"enum_dispatch",
"futures 0.3.23",
"futures-util",
"indexmap",
"indicatif",
"itertools",
"jsonrpc-core",
"jsonrpc-http-server",
"lazy_static",
"log", "log",
"quinn",
"quinn-proto",
"quinn-udp",
"rand 0.7.3",
"rand_chacha 0.2.2",
"rayon",
"reqwest",
"rustls 0.20.6",
"semver 1.0.13",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-clap-utils",
"solana-faucet",
"solana-logger 1.12.0",
"solana-measure", "solana-measure",
"solana-metrics", "solana-pubsub-client",
"solana-net-utils", "solana-rpc-client",
"solana-perf", "solana-rpc-client-api",
"solana-rpc-client-nonce-utils",
"solana-sdk 1.12.0", "solana-sdk 1.12.0",
"solana-streamer", "solana-thin-client",
"solana-transaction-status", "solana-tpu-client",
"solana-version",
"solana-vote-program",
"spl-token-2022",
"thiserror",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tungstenite",
"url 2.2.2",
] ]
[[package]] [[package]]
@ -5911,6 +5869,29 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "solana-pubsub-client"
version = "1.12.0"
dependencies = [
"crossbeam-channel",
"futures-util",
"log",
"reqwest",
"semver 1.0.13",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"thiserror",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tungstenite",
"url 2.2.2",
]
[[package]] [[package]]
name = "solana-rayon-threadlimit" name = "solana-rayon-threadlimit"
version = "1.12.0" version = "1.12.0"
@ -5992,6 +5973,72 @@ dependencies = [
"tokio-util 0.6.9", "tokio-util 0.6.9",
] ]
[[package]]
name = "solana-rpc-client"
version = "1.12.0"
dependencies = [
"assert_matches",
"async-trait",
"base64 0.13.0",
"bincode",
"bs58",
"crossbeam-channel",
"futures 0.3.23",
"indicatif",
"jsonrpc-core",
"jsonrpc-http-server",
"log",
"reqwest",
"semver 1.0.13",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-transaction-status",
"solana-version",
"solana-vote-program",
"tokio",
]
[[package]]
name = "solana-rpc-client-api"
version = "1.12.0"
dependencies = [
"base64 0.13.0",
"bs58",
"jsonrpc-core",
"reqwest",
"semver 1.0.13",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-sdk 1.12.0",
"solana-transaction-status",
"solana-version",
"spl-token-2022",
"thiserror",
]
[[package]]
name = "solana-rpc-client-nonce-utils"
version = "1.12.0"
dependencies = [
"anyhow",
"clap 2.33.3",
"futures 0.3.23",
"serde_json",
"solana-account-decoder",
"solana-clap-utils",
"solana-rpc-client",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "solana-rpc-test" name = "solana-rpc-test"
version = "1.12.0" version = "1.12.0"
@ -6389,6 +6436,20 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "solana-thin-client"
version = "1.12.0"
dependencies = [
"bincode",
"log",
"rayon",
"solana-logger 1.12.0",
"solana-rpc-client",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-tpu-client",
]
[[package]] [[package]]
name = "solana-tokens" name = "solana-tokens"
version = "1.12.0" version = "1.12.0"
@ -6420,6 +6481,43 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "solana-tpu-client"
version = "1.12.0"
dependencies = [
"async-mutex",
"async-trait",
"bincode",
"crossbeam-channel",
"enum_dispatch",
"futures 0.3.23",
"futures-util",
"indexmap",
"indicatif",
"itertools",
"lazy_static",
"log",
"quinn",
"quinn-proto",
"quinn-udp",
"rand 0.7.3",
"rand_chacha 0.2.2",
"rayon",
"rustls 0.20.6",
"solana-logger 1.12.0",
"solana-measure",
"solana-metrics",
"solana-net-utils",
"solana-perf",
"solana-pubsub-client",
"solana-rpc-client",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-streamer",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "solana-transaction-dos" name = "solana-transaction-dos"
version = "1.12.0" version = "1.12.0"

View File

@ -58,10 +58,14 @@ members = [
"programs/stake", "programs/stake",
"programs/vote", "programs/vote",
"programs/zk-token-proof", "programs/zk-token-proof",
"pubsub-client",
"rayon-threadlimit", "rayon-threadlimit",
"rbpf-cli", "rbpf-cli",
"remote-wallet", "remote-wallet",
"rpc", "rpc",
"rpc-client",
"rpc-client-api",
"rpc-client-nonce-utils",
"rpc-test", "rpc-test",
"runtime", "runtime",
"runtime/store-tool", "runtime/store-tool",
@ -78,7 +82,9 @@ members = [
"streamer", "streamer",
"sys-tuner", "sys-tuner",
"test-validator", "test-validator",
"thin-client",
"tokens", "tokens",
"tpu-client",
"transaction-dos", "transaction-dos",
"transaction-status", "transaction-status",
"upload-perf", "upload-perf",

View File

@ -39,6 +39,7 @@ solana-faucet = { path = "../faucet", version = "=1.12.0" }
solana-logger = { path = "../logger", version = "=1.12.0" } solana-logger = { path = "../logger", version = "=1.12.0" }
solana-program-runtime = { path = "../program-runtime", version = "=1.12.0" } solana-program-runtime = { path = "../program-runtime", version = "=1.12.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.12.0" } solana-remote-wallet = { path = "../remote-wallet", version = "=1.12.0" }
solana-rpc-client = { path = "../rpc-client", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" } solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.12.0" } solana-transaction-status = { path = "../transaction-status", version = "=1.12.0" }
solana-version = { path = "../version", version = "=1.12.0" } solana-version = { path = "../version", version = "=1.12.0" }

View File

@ -1713,10 +1713,10 @@ mod tests {
serde_json::{json, Value}, serde_json::{json, Value},
solana_client::{ solana_client::{
blockhash_query, blockhash_query,
mock_sender_for_cli::SIGNATURE,
rpc_request::RpcRequest, rpc_request::RpcRequest,
rpc_response::{Response, RpcResponseContext}, rpc_response::{Response, RpcResponseContext},
}, },
solana_rpc_client::mock_sender_for_cli::SIGNATURE,
solana_sdk::{ solana_sdk::{
pubkey::Pubkey, pubkey::Pubkey,
signature::{ signature::{

View File

@ -10,60 +10,17 @@ license = "Apache-2.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
async-mutex = "1.4.0"
async-trait = "0.1.57"
base64 = "0.13.0"
bincode = "1.3.3"
bs58 = "0.4.0"
bytes = "1.2.1"
clap = "2.33.0"
crossbeam-channel = "0.5"
enum_dispatch = "0.3.8"
futures = "0.3"
futures-util = "0.3.21"
indexmap = "1.9.1"
indicatif = "0.17.0"
itertools = "0.10.2"
jsonrpc-core = "18.0.0"
lazy_static = "1.4.0"
log = "0.4.17" log = "0.4.17"
quinn = "0.8.4"
quinn-proto = "0.8.4"
quinn-udp = "0.1.3"
rand = "0.7.0"
rand_chacha = "0.2.2"
rayon = "1.5.3"
reqwest = { version = "0.11.11", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] }
rustls = { version = "0.20.6", features = ["dangerous_configuration"] }
semver = "1.0.13"
serde = "1.0.143"
serde_derive = "1.0.103"
serde_json = "1.0.83"
solana-account-decoder = { path = "../account-decoder", version = "=1.12.0" }
solana-clap-utils = { path = "../clap-utils", version = "=1.12.0" }
solana-faucet = { path = "../faucet", version = "=1.12.0" }
solana-measure = { path = "../measure", version = "=1.12.0" } solana-measure = { path = "../measure", version = "=1.12.0" }
solana-metrics = { path = "../metrics", version = "=1.12.0" } solana-pubsub-client = { path = "../pubsub-client", version = "=1.12.0" }
solana-net-utils = { path = "../net-utils", version = "=1.12.0" } solana-rpc-client = { path = "../rpc-client", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
solana-rpc-client-nonce-utils = { path = "../rpc-client-nonce-utils", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" } solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-streamer = { path = "../streamer", version = "=1.12.0" } solana-thin-client = { path = "../thin-client", version = "=1.12.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.12.0" } solana-tpu-client = { path = "../tpu-client", version = "=1.12.0" }
solana-version = { path = "../version", version = "=1.12.0" }
solana-vote-program = { path = "../programs/vote", version = "=1.12.0" }
spl-token-2022 = { version = "=0.4.3", features = ["no-entrypoint"] }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1.9"
tokio-tungstenite = { version = "0.17.2", features = ["rustls-tls-webpki-roots"] }
tungstenite = { version = "0.17.2", features = ["rustls-tls-webpki-roots"] }
url = "2.2.2"
[dev-dependencies] [dev-dependencies]
anyhow = "1.0.58"
assert_matches = "1.5.0"
jsonrpc-http-server = "18.0.0"
solana-logger = { path = "../logger", version = "=1.12.0" }
solana-perf = { path = "../perf", version = "=1.12.0" }
[package.metadata.docs.rs] [package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"] targets = ["x86_64-unknown-linux-gnu"]

View File

@ -1,212 +0,0 @@
pub use reqwest;
use {
crate::{nonblocking::quic_client::QuicError, rpc_request, rpc_response},
quinn::ConnectError,
solana_faucet::faucet::FaucetError,
solana_sdk::{
signature::SignerError, transaction::TransactionError, transport::TransportError,
},
std::io,
thiserror::Error,
}; // export `reqwest` for clients
#[derive(Error, Debug)]
pub enum ClientErrorKind {
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Reqwest(#[from] reqwest::Error),
#[error(transparent)]
RpcError(#[from] rpc_request::RpcError),
#[error(transparent)]
SerdeJson(#[from] serde_json::error::Error),
#[error(transparent)]
SigningError(#[from] SignerError),
#[error(transparent)]
TransactionError(#[from] TransactionError),
#[error(transparent)]
FaucetError(#[from] FaucetError),
#[error("Custom: {0}")]
Custom(String),
}
impl ClientErrorKind {
pub fn get_transaction_error(&self) -> Option<TransactionError> {
match self {
Self::RpcError(rpc_request::RpcError::RpcResponseError {
data:
rpc_request::RpcResponseErrorData::SendTransactionPreflightFailure(
rpc_response::RpcSimulateTransactionResult {
err: Some(tx_err), ..
},
),
..
}) => Some(tx_err.clone()),
Self::TransactionError(tx_err) => Some(tx_err.clone()),
_ => None,
}
}
}
impl From<TransportError> for ClientErrorKind {
fn from(err: TransportError) -> Self {
match err {
TransportError::IoError(err) => Self::Io(err),
TransportError::TransactionError(err) => Self::TransactionError(err),
TransportError::Custom(err) => Self::Custom(err),
}
}
}
impl From<ClientErrorKind> for TransportError {
fn from(client_error_kind: ClientErrorKind) -> Self {
match client_error_kind {
ClientErrorKind::Io(err) => Self::IoError(err),
ClientErrorKind::TransactionError(err) => Self::TransactionError(err),
ClientErrorKind::Reqwest(err) => Self::Custom(format!("{:?}", err)),
ClientErrorKind::RpcError(err) => Self::Custom(format!("{:?}", err)),
ClientErrorKind::SerdeJson(err) => Self::Custom(format!("{:?}", err)),
ClientErrorKind::SigningError(err) => Self::Custom(format!("{:?}", err)),
ClientErrorKind::FaucetError(err) => Self::Custom(format!("{:?}", err)),
ClientErrorKind::Custom(err) => Self::Custom(format!("{:?}", err)),
}
}
}
impl From<QuicError> for ClientErrorKind {
fn from(quic_error: QuicError) -> Self {
Self::Custom(format!("{:?}", quic_error))
}
}
impl From<ConnectError> for ClientErrorKind {
fn from(connect_error: ConnectError) -> Self {
Self::Custom(format!("{:?}", connect_error))
}
}
#[derive(Error, Debug)]
#[error("{kind}")]
pub struct ClientError {
pub request: Option<rpc_request::RpcRequest>,
#[source]
pub kind: ClientErrorKind,
}
impl ClientError {
pub fn new_with_request(kind: ClientErrorKind, request: rpc_request::RpcRequest) -> Self {
Self {
request: Some(request),
kind,
}
}
pub fn into_with_request(self, request: rpc_request::RpcRequest) -> Self {
Self {
request: Some(request),
..self
}
}
pub fn request(&self) -> Option<&rpc_request::RpcRequest> {
self.request.as_ref()
}
pub fn kind(&self) -> &ClientErrorKind {
&self.kind
}
pub fn get_transaction_error(&self) -> Option<TransactionError> {
self.kind.get_transaction_error()
}
}
impl From<ClientErrorKind> for ClientError {
fn from(kind: ClientErrorKind) -> Self {
Self {
request: None,
kind,
}
}
}
impl From<TransportError> for ClientError {
fn from(err: TransportError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<ClientError> for TransportError {
fn from(client_error: ClientError) -> Self {
client_error.kind.into()
}
}
impl From<std::io::Error> for ClientError {
fn from(err: std::io::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<reqwest::Error> for ClientError {
fn from(err: reqwest::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<rpc_request::RpcError> for ClientError {
fn from(err: rpc_request::RpcError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<serde_json::error::Error> for ClientError {
fn from(err: serde_json::error::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<SignerError> for ClientError {
fn from(err: SignerError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<TransactionError> for ClientError {
fn from(err: TransactionError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<FaucetError> for ClientError {
fn from(err: FaucetError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
pub type Result<T> = std::result::Result<T, ClientError>;

View File

@ -1,38 +1,120 @@
#![allow(clippy::integer_arithmetic)] #![allow(clippy::integer_arithmetic)]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate solana_metrics;
pub mod blockhash_query;
pub mod client_error;
pub mod connection_cache;
pub(crate) mod http_sender;
pub(crate) mod mock_sender;
pub mod nonblocking;
pub mod nonce_utils;
pub mod pubsub_client;
pub mod quic_client;
pub mod rpc_cache;
pub mod rpc_client;
pub mod rpc_config;
pub mod rpc_custom_error;
pub mod rpc_deprecated_config;
pub mod rpc_filter;
pub mod rpc_request;
pub mod rpc_response;
pub mod rpc_sender;
pub mod spinner;
pub mod thin_client;
pub mod tpu_client;
pub mod tpu_connection;
pub mod transaction_executor; pub mod transaction_executor;
pub mod udp_client;
pub mod mock_sender_for_cli { pub use solana_rpc_client::mock_sender_for_cli;
/// Magic `SIGNATURE` value used by `solana-cli` unit tests.
/// Please don't use this constant. pub mod blockhash_query {
pub const SIGNATURE: &str = pub use solana_rpc_client_nonce_utils::blockhash_query::*;
"43yNSFC6fYTuPgTNFFhF4axw7AfWxB2BPdurme8yrsWEYwm8299xh8n6TAHjGymiSub1XtyxTNyd9GBfY2hxoBw8"; }
pub mod client_error {
pub use solana_rpc_client_api::client_error::{
reqwest, Error as ClientError, ErrorKind as ClientErrorKind, Result,
};
}
pub mod connection_cache {
pub use solana_tpu_client::connection_cache::*;
}
pub mod nonblocking {
pub mod blockhash_query {
pub use solana_rpc_client_nonce_utils::nonblocking::blockhash_query::*;
}
/// Durable transaction nonce helpers.
pub mod nonce_utils {
pub use solana_rpc_client_nonce_utils::nonblocking::*;
}
pub mod pubsub_client {
pub use solana_pubsub_client::nonblocking::pubsub_client::*;
}
/// Simple nonblocking client that connects to a given UDP port with the QUIC protocol
/// and provides an interface for sending transactions which is restricted by the
/// server's flow control.
pub mod quic_client {
pub use solana_tpu_client::nonblocking::quic_client::*;
}
/// Communication with a Solana node over RPC asynchronously .
///
/// Software that interacts with the Solana blockchain, whether querying its
/// state or submitting transactions, communicates with a Solana node over
/// [JSON-RPC], using the [`RpcClient`] type.
///
/// [JSON-RPC]: https://www.jsonrpc.org/specification
pub mod rpc_client {
pub use solana_rpc_client::nonblocking::rpc_client::*;
}
pub mod tpu_client {
pub use solana_tpu_client::nonblocking::tpu_client::*;
}
/// Trait defining async send functions, to be used for UDP or QUIC sending
pub mod tpu_connection {
pub use solana_tpu_client::nonblocking::tpu_connection::*;
}
/// Simple UDP client that communicates with the given UDP port with UDP and provides
/// an interface for sending transactions
pub mod udp_client {
pub use solana_tpu_client::nonblocking::udp_client::*;
}
}
/// Durable transaction nonce helpers.
pub mod nonce_utils {
pub use solana_rpc_client_nonce_utils::*;
}
pub mod pubsub_client {
pub use solana_pubsub_client::pubsub_client::*;
}
/// Simple client that connects to a given UDP port with the QUIC protocol and provides
/// an interface for sending transactions which is restricted by the server's flow control.
pub mod quic_client {
pub use solana_tpu_client::quic_client::*;
}
/// Communication with a Solana node over RPC.
///
/// Software that interacts with the Solana blockchain, whether querying its
/// state or submitting transactions, communicates with a Solana node over
/// [JSON-RPC], using the [`RpcClient`] type.
///
/// [JSON-RPC]: https://www.jsonrpc.org/specification
pub mod rpc_client {
pub use solana_rpc_client::rpc_client::*;
}
pub mod rpc_config {
pub use solana_rpc_client_api::config::*;
}
/// Implementation defined RPC server errors
pub mod rpc_custom_error {
pub use solana_rpc_client_api::custom_error::*;
}
pub mod rpc_deprecated_config {
pub use solana_rpc_client_api::deprecated_config::*;
}
pub mod rpc_filter {
pub use solana_rpc_client_api::filter::*;
}
pub mod rpc_request {
pub use solana_rpc_client_api::request::*;
}
pub mod rpc_response {
pub use solana_rpc_client_api::response::*;
}
/// A transport for RPC calls.
pub mod rpc_sender {
pub use solana_rpc_client::rpc_sender::*;
}
/// The `thin_client` module is a client-side object that interfaces with
/// a server-side TPU. Client code should use this object instead of writing
/// messages to the network directly. The binary encoding of its messages are
/// unstable and may change in future releases.
pub mod thin_client {
pub use solana_thin_client::thin_client::*;
}
pub mod tpu_client {
pub use solana_tpu_client::tpu_client::*;
}
pub mod tpu_connection {
pub use solana_tpu_client::tpu_connection::*;
}
/// Simple TPU client that communicates with the given UDP port with UDP and provides
/// an interface for sending transactions
pub mod udp_client {
pub use solana_tpu_client::udp_client::*;
} }

View File

@ -1,8 +0,0 @@
pub mod blockhash_query;
pub mod nonce_utils;
pub mod pubsub_client;
pub mod quic_client;
pub mod rpc_client;
pub mod tpu_client;
pub mod tpu_connection;
pub mod udp_client;

View File

@ -1,40 +0,0 @@
//! Spinner creator
use {
indicatif::{ProgressBar, ProgressStyle},
std::time::Duration,
};
pub(crate) fn new_progress_bar() -> ProgressBar {
let progress_bar = ProgressBar::new(42);
progress_bar.set_style(
ProgressStyle::default_spinner()
.template("{spinner:.green} {wide_msg}")
.expect("ProgresStyle::template direct input to be correct"),
);
progress_bar.enable_steady_tick(Duration::from_millis(100));
progress_bar
}
pub(crate) fn set_message_for_confirmed_transactions(
progress_bar: &ProgressBar,
confirmed_transactions: u32,
total_transactions: usize,
block_height: Option<u64>,
last_valid_block_height: u64,
status: &str,
) {
progress_bar.set_message(format!(
"{:>5.1}% | {:<40}{}",
confirmed_transactions as f64 * 100. / total_transactions as f64,
status,
match block_height {
Some(block_height) => format!(
" [block height {}; re-sign in {} blocks]",
block_height,
last_valid_block_height.saturating_sub(block_height),
),
None => String::new(),
},
));
}

View File

@ -1,8 +1,8 @@
#![allow(clippy::integer_arithmetic)] #![allow(clippy::integer_arithmetic)]
use { use {
crate::rpc_client::RpcClient,
log::*, log::*,
solana_measure::measure::Measure, solana_measure::measure::Measure,
solana_rpc_client::rpc_client::RpcClient,
solana_sdk::{ solana_sdk::{
commitment_config::CommitmentConfig, signature::Signature, timing::timestamp, commitment_config::CommitmentConfig, signature::Signature, timing::timestamp,
transaction::Transaction, transaction::Transaction,

173
programs/bpf/Cargo.lock generated
View File

@ -4649,53 +4649,15 @@ dependencies = [
name = "solana-client" name = "solana-client"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"async-mutex",
"async-trait",
"base64 0.13.0",
"bincode",
"bs58",
"bytes",
"clap 2.33.3",
"crossbeam-channel",
"enum_dispatch",
"futures 0.3.23",
"futures-util",
"indexmap",
"indicatif",
"itertools",
"jsonrpc-core",
"lazy_static",
"log", "log",
"quinn",
"quinn-proto",
"quinn-udp",
"rand 0.7.3",
"rand_chacha 0.2.2",
"rayon",
"reqwest",
"rustls 0.20.6",
"semver",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-clap-utils",
"solana-faucet",
"solana-measure", "solana-measure",
"solana-metrics", "solana-pubsub-client",
"solana-net-utils", "solana-rpc-client",
"solana-rpc-client-api",
"solana-rpc-client-nonce-utils",
"solana-sdk 1.12.0", "solana-sdk 1.12.0",
"solana-streamer", "solana-thin-client",
"solana-transaction-status", "solana-tpu-client",
"solana-version",
"solana-vote-program",
"spl-token-2022",
"thiserror",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tungstenite",
"url 2.2.2",
] ]
[[package]] [[package]]
@ -5312,6 +5274,29 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "solana-pubsub-client"
version = "1.12.0"
dependencies = [
"crossbeam-channel",
"futures-util",
"log",
"reqwest",
"semver",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"thiserror",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tungstenite",
"url 2.2.2",
]
[[package]] [[package]]
name = "solana-rayon-threadlimit" name = "solana-rayon-threadlimit"
version = "1.12.0" version = "1.12.0"
@ -5388,6 +5373,61 @@ dependencies = [
"tokio-util 0.6.9", "tokio-util 0.6.9",
] ]
[[package]]
name = "solana-rpc-client"
version = "1.12.0"
dependencies = [
"async-trait",
"base64 0.13.0",
"bincode",
"bs58",
"indicatif",
"log",
"reqwest",
"semver",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-transaction-status",
"solana-version",
"solana-vote-program",
"tokio",
]
[[package]]
name = "solana-rpc-client-api"
version = "1.12.0"
dependencies = [
"base64 0.13.0",
"bs58",
"jsonrpc-core",
"reqwest",
"semver",
"serde",
"serde_derive",
"serde_json",
"solana-account-decoder",
"solana-sdk 1.12.0",
"solana-transaction-status",
"solana-version",
"spl-token-2022",
"thiserror",
]
[[package]]
name = "solana-rpc-client-nonce-utils"
version = "1.12.0"
dependencies = [
"clap 2.33.3",
"solana-clap-utils",
"solana-rpc-client",
"solana-sdk 1.12.0",
"thiserror",
]
[[package]] [[package]]
name = "solana-runtime" name = "solana-runtime"
version = "1.12.0" version = "1.12.0"
@ -5719,6 +5759,51 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "solana-thin-client"
version = "1.12.0"
dependencies = [
"bincode",
"log",
"solana-rpc-client",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-tpu-client",
]
[[package]]
name = "solana-tpu-client"
version = "1.12.0"
dependencies = [
"async-mutex",
"async-trait",
"bincode",
"enum_dispatch",
"futures 0.3.23",
"futures-util",
"indexmap",
"indicatif",
"itertools",
"lazy_static",
"log",
"quinn",
"quinn-proto",
"quinn-udp",
"rand 0.7.3",
"rayon",
"rustls 0.20.6",
"solana-measure",
"solana-metrics",
"solana-net-utils",
"solana-pubsub-client",
"solana-rpc-client",
"solana-rpc-client-api",
"solana-sdk 1.12.0",
"solana-streamer",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "solana-transaction-status" name = "solana-transaction-status"
version = "1.12.0" version = "1.12.0"

34
pubsub-client/Cargo.toml Normal file
View File

@ -0,0 +1,34 @@
[package]
name = "solana-pubsub-client"
version = "1.12.0"
description = "Solana Pubsub Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-pubsub-client"
edition = "2021"
[dependencies]
crossbeam-channel = "0.5"
futures-util = "0.3.21"
log = "0.4.17"
reqwest = { version = "0.11.11", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] }
semver = "1.0.13"
serde = "1.0.143"
serde_derive = "1.0.103"
serde_json = "1.0.83"
solana-account-decoder = { path = "../account-decoder", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1.9"
tokio-tungstenite = { version = "0.17.2", features = ["rustls-tls-webpki-roots"] }
tungstenite = { version = "0.17.2", features = ["rustls-tls-webpki-roots"] }
url = "2.2.2"
[dev-dependencies]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

4
pubsub-client/src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
#![allow(clippy::integer_arithmetic)]
pub mod nonblocking;
pub mod pubsub_client;

View File

@ -0,0 +1 @@
pub mod pubsub_client;

View File

@ -1,17 +1,4 @@
use { use {
crate::{
http_sender::RpcErrorObject,
rpc_config::{
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
RpcTransactionLogsFilter,
},
rpc_filter::maybe_map_filters,
rpc_response::{
Response as RpcResponse, RpcBlockUpdate, RpcKeyedAccount, RpcLogsResponse,
RpcSignatureResult, RpcVersionInfo, RpcVote, SlotInfo, SlotUpdate,
},
},
futures_util::{ futures_util::{
future::{ready, BoxFuture, FutureExt}, future::{ready, BoxFuture, FutureExt},
sink::SinkExt, sink::SinkExt,
@ -21,6 +8,19 @@ use {
serde::de::DeserializeOwned, serde::de::DeserializeOwned,
serde_json::{json, Map, Value}, serde_json::{json, Map, Value},
solana_account_decoder::UiAccount, solana_account_decoder::UiAccount,
solana_rpc_client_api::{
config::{
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
RpcTransactionLogsFilter,
},
error_object::RpcErrorObject,
filter::maybe_map_filters,
response::{
Response as RpcResponse, RpcBlockUpdate, RpcKeyedAccount, RpcLogsResponse,
RpcSignatureResult, RpcVersionInfo, RpcVote, SlotInfo, SlotUpdate,
},
},
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}, solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature},
std::collections::BTreeMap, std::collections::BTreeMap,
thiserror::Error, thiserror::Error,

View File

@ -1,17 +1,5 @@
pub use crate::nonblocking::pubsub_client::PubsubClientError; pub use crate::nonblocking::pubsub_client::PubsubClientError;
use { use {
crate::{
rpc_config::{
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
RpcTransactionLogsFilter,
},
rpc_filter,
rpc_response::{
Response as RpcResponse, RpcBlockUpdate, RpcKeyedAccount, RpcLogsResponse,
RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate,
},
},
crossbeam_channel::{unbounded, Receiver, Sender}, crossbeam_channel::{unbounded, Receiver, Sender},
log::*, log::*,
serde::de::DeserializeOwned, serde::de::DeserializeOwned,
@ -21,6 +9,18 @@ use {
Map, Value, Map, Value,
}, },
solana_account_decoder::UiAccount, solana_account_decoder::UiAccount,
solana_rpc_client_api::{
config::{
RpcAccountInfoConfig, RpcBlockSubscribeConfig, RpcBlockSubscribeFilter,
RpcProgramAccountsConfig, RpcSignatureSubscribeConfig, RpcTransactionLogsConfig,
RpcTransactionLogsFilter,
},
filter,
response::{
Response as RpcResponse, RpcBlockUpdate, RpcKeyedAccount, RpcLogsResponse,
RpcSignatureResult, RpcVote, SlotInfo, SlotUpdate,
},
},
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}, solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature},
std::{ std::{
marker::PhantomData, marker::PhantomData,
@ -396,7 +396,7 @@ impl PubsubClient {
let node_version = PubsubProgramClientSubscription::get_version(&socket_clone).ok(); let node_version = PubsubProgramClientSubscription::get_version(&socket_clone).ok();
// If node does not support the pubsub `getVersion` method, assume version is old // If node does not support the pubsub `getVersion` method, assume version is old
// and filters should be mapped (node_version.is_none()). // and filters should be mapped (node_version.is_none()).
rpc_filter::maybe_map_filters(node_version, filters) filter::maybe_map_filters(node_version, filters)
.map_err(PubsubClientError::RequestError)?; .map_err(PubsubClientError::RequestError)?;
} }
} }

31
rpc-client-api/Cargo.toml Normal file
View File

@ -0,0 +1,31 @@
[package]
name = "solana-rpc-client-api"
version = "1.12.0"
description = "Solana Client Common Utilities"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-rpc-client-api"
edition = "2021"
[dependencies]
base64 = "0.13.0"
bs58 = "0.4.0"
jsonrpc-core = "18.0.0"
reqwest = { version = "0.11.11", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] }
semver = "1.0.13"
serde = "1.0.143"
serde_derive = "1.0.103"
serde_json = "1.0.83"
solana-account-decoder = { path = "../account-decoder", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.12.0" }
solana-version = { path = "../version", version = "=1.12.0" }
spl-token-2022 = { version = "=0.4.3", features = ["no-entrypoint"] }
thiserror = "1.0"
[dev-dependencies]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@ -0,0 +1,186 @@
pub use reqwest;
use {
crate::{request, response},
solana_sdk::{
signature::SignerError, transaction::TransactionError, transport::TransportError,
},
std::io,
thiserror::Error as ThisError,
};
#[derive(ThisError, Debug)]
pub enum ErrorKind {
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Reqwest(#[from] reqwest::Error),
#[error(transparent)]
RpcError(#[from] request::RpcError),
#[error(transparent)]
SerdeJson(#[from] serde_json::error::Error),
#[error(transparent)]
SigningError(#[from] SignerError),
#[error(transparent)]
TransactionError(#[from] TransactionError),
#[error("Custom: {0}")]
Custom(String),
}
impl ErrorKind {
pub fn get_transaction_error(&self) -> Option<TransactionError> {
match self {
Self::RpcError(request::RpcError::RpcResponseError {
data:
request::RpcResponseErrorData::SendTransactionPreflightFailure(
response::RpcSimulateTransactionResult {
err: Some(tx_err), ..
},
),
..
}) => Some(tx_err.clone()),
Self::TransactionError(tx_err) => Some(tx_err.clone()),
_ => None,
}
}
}
impl From<TransportError> for ErrorKind {
fn from(err: TransportError) -> Self {
match err {
TransportError::IoError(err) => Self::Io(err),
TransportError::TransactionError(err) => Self::TransactionError(err),
TransportError::Custom(err) => Self::Custom(err),
}
}
}
impl From<ErrorKind> for TransportError {
fn from(client_error_kind: ErrorKind) -> Self {
match client_error_kind {
ErrorKind::Io(err) => Self::IoError(err),
ErrorKind::TransactionError(err) => Self::TransactionError(err),
ErrorKind::Reqwest(err) => Self::Custom(format!("{:?}", err)),
ErrorKind::RpcError(err) => Self::Custom(format!("{:?}", err)),
ErrorKind::SerdeJson(err) => Self::Custom(format!("{:?}", err)),
ErrorKind::SigningError(err) => Self::Custom(format!("{:?}", err)),
ErrorKind::Custom(err) => Self::Custom(format!("{:?}", err)),
}
}
}
#[derive(ThisError, Debug)]
#[error("{kind}")]
pub struct Error {
pub request: Option<request::RpcRequest>,
#[source]
pub kind: ErrorKind,
}
impl Error {
pub fn new_with_request(kind: ErrorKind, request: request::RpcRequest) -> Self {
Self {
request: Some(request),
kind,
}
}
pub fn into_with_request(self, request: request::RpcRequest) -> Self {
Self {
request: Some(request),
..self
}
}
pub fn request(&self) -> Option<&request::RpcRequest> {
self.request.as_ref()
}
pub fn kind(&self) -> &ErrorKind {
&self.kind
}
pub fn get_transaction_error(&self) -> Option<TransactionError> {
self.kind.get_transaction_error()
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Self {
request: None,
kind,
}
}
}
impl From<TransportError> for Error {
fn from(err: TransportError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<Error> for TransportError {
fn from(client_error: Error) -> Self {
client_error.kind.into()
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<request::RpcError> for Error {
fn from(err: request::RpcError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<serde_json::error::Error> for Error {
fn from(err: serde_json::error::Error) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<SignerError> for Error {
fn from(err: SignerError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Self {
Self {
request: None,
kind: err.into(),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -1,5 +1,5 @@
use { use {
crate::rpc_filter::RpcFilterType, crate::filter::RpcFilterType,
solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}, solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig},
solana_sdk::{ solana_sdk::{
clock::{Epoch, Slot}, clock::{Epoch, Slot},

View File

@ -1,6 +1,6 @@
//! Implementation defined RPC server errors //! Implementation defined RPC server errors
use { use {
crate::rpc_response::RpcSimulateTransactionResult, crate::response::RpcSimulateTransactionResult,
jsonrpc_core::{Error, ErrorCode}, jsonrpc_core::{Error, ErrorCode},
solana_sdk::clock::Slot, solana_sdk::clock::Slot,
solana_transaction_status::EncodeError, solana_transaction_status::EncodeError,

View File

@ -1,6 +1,6 @@
#![allow(deprecated)] #![allow(deprecated)]
use { use {
crate::rpc_config::{ crate::config::{
EncodingConfig, RpcBlockConfig, RpcEncodingConfigWrapper, RpcTransactionConfig, EncodingConfig, RpcBlockConfig, RpcEncodingConfigWrapper, RpcTransactionConfig,
}, },
solana_sdk::{clock::Slot, commitment_config::CommitmentConfig}, solana_sdk::{clock::Slot, commitment_config::CommitmentConfig},

View File

@ -0,0 +1,5 @@
#[derive(Deserialize, Debug)]
pub struct RpcErrorObject {
pub code: i64,
pub message: String,
}

View File

@ -259,7 +259,7 @@ impl From<RpcMemcmp> for Memcmp {
} }
} }
pub(crate) fn maybe_map_filters( pub fn maybe_map_filters(
node_version: Option<semver::Version>, node_version: Option<semver::Version>,
filters: &mut [RpcFilterType], filters: &mut [RpcFilterType],
) -> Result<(), String> { ) -> Result<(), String> {

13
rpc-client-api/src/lib.rs Normal file
View File

@ -0,0 +1,13 @@
#![allow(clippy::integer_arithmetic)]
pub mod client_error;
pub mod config;
pub mod custom_error;
pub mod deprecated_config;
pub mod error_object;
pub mod filter;
pub mod request;
pub mod response;
#[macro_use]
extern crate serde_derive;

View File

@ -1,5 +1,5 @@
use { use {
crate::rpc_response::RpcSimulateTransactionResult, crate::response::RpcSimulateTransactionResult,
serde_json::{json, Value}, serde_json::{json, Value},
solana_sdk::{clock::Slot, pubkey::Pubkey}, solana_sdk::{clock::Slot, pubkey::Pubkey},
std::fmt, std::fmt,
@ -208,7 +208,7 @@ pub const MAX_GET_SLOT_LEADERS: usize = 5000;
pub const DELINQUENT_VALIDATOR_SLOT_DISTANCE: u64 = 128; pub const DELINQUENT_VALIDATOR_SLOT_DISTANCE: u64 = 128;
impl RpcRequest { impl RpcRequest {
pub(crate) fn build_request_json(self, id: u64, params: Value) -> Value { pub fn build_request_json(self, id: u64, params: Value) -> Value {
let jsonrpc = "2.0"; let jsonrpc = "2.0";
json!({ json!({
"jsonrpc": jsonrpc, "jsonrpc": jsonrpc,
@ -274,7 +274,7 @@ pub enum TokenAccountsFilter {
mod tests { mod tests {
use { use {
super::*, super::*,
crate::rpc_config::RpcTokenAccountsFilter, crate::config::RpcTokenAccountsFilter,
solana_sdk::commitment_config::{CommitmentConfig, CommitmentLevel}, solana_sdk::commitment_config::{CommitmentConfig, CommitmentLevel},
}; };

View File

@ -0,0 +1,28 @@
[package]
name = "solana-rpc-client-nonce-utils"
version = "1.12.0"
description = "Solana RPC Client Nonce Utilities"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-nonce-client"
edition = "2021"
[dependencies]
clap = "2.33.0"
solana-clap-utils = { path = "../clap-utils", version = "=1.12.0" }
solana-rpc-client = { path = "../rpc-client", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
thiserror = "1.0"
[dev-dependencies]
anyhow = "1.0.58"
futures = "0.3"
serde_json = "1.0.83"
solana-account-decoder = { path = "../account-decoder", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
tokio = { version = "1", features = ["full"] }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@ -1,11 +1,11 @@
use { use {
crate::{nonce_utils, rpc_client::RpcClient},
clap::ArgMatches, clap::ArgMatches,
solana_clap_utils::{ solana_clap_utils::{
input_parsers::{pubkey_of, value_of}, input_parsers::{pubkey_of, value_of},
nonce::*, nonce::*,
offline::*, offline::*,
}, },
solana_rpc_client::rpc_client::RpcClient,
solana_sdk::{ solana_sdk::{
commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, hash::Hash, commitment_config::CommitmentConfig, fee_calculator::FeeCalculator, hash::Hash,
pubkey::Pubkey, pubkey::Pubkey,
@ -35,8 +35,8 @@ impl Source {
} }
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
let data = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment) let data = crate::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce_utils::data_from_account(a))?; .and_then(|ref a| crate::data_from_account(a))?;
Ok((data.blockhash(), data.fee_calculator)) Ok((data.blockhash(), data.fee_calculator))
} }
} }
@ -61,8 +61,8 @@ impl Source {
Ok(res) Ok(res)
} }
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
let res = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment)?; let res = crate::get_account_with_commitment(rpc_client, pubkey, commitment)?;
let res = nonce_utils::data_from_account(&res)?; let res = crate::data_from_account(&res)?;
Ok(Some(res) Ok(Some(res)
.filter(|d| d.blockhash() == *blockhash) .filter(|d| d.blockhash() == *blockhash)
.map(|d| d.fee_calculator)) .map(|d| d.fee_calculator))
@ -82,8 +82,8 @@ impl Source {
} }
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
let data = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment) let data = crate::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce_utils::data_from_account(a))?; .and_then(|ref a| crate::data_from_account(a))?;
Ok(data.blockhash()) Ok(data.blockhash())
} }
} }
@ -99,8 +99,8 @@ impl Source {
Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment)?, Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment)?,
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
let _ = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment) let _ = crate::get_account_with_commitment(rpc_client, pubkey, commitment)
.and_then(|ref a| nonce_utils::data_from_account(a))?; .and_then(|ref a| crate::data_from_account(a))?;
true true
} }
}) })
@ -185,14 +185,14 @@ impl Default for BlockhashQuery {
mod tests { mod tests {
use { use {
super::*, super::*,
crate::{ crate::blockhash_query,
blockhash_query,
rpc_request::RpcRequest,
rpc_response::{Response, RpcFeeCalculator, RpcFees, RpcResponseContext},
},
clap::App, clap::App,
serde_json::{self, json}, serde_json::{self, json},
solana_account_decoder::{UiAccount, UiAccountEncoding}, solana_account_decoder::{UiAccount, UiAccountEncoding},
solana_rpc_client_api::{
request::RpcRequest,
response::{Response, RpcFeeCalculator, RpcFees, RpcResponseContext},
},
solana_sdk::{ solana_sdk::{
account::Account, account::Account,
hash::hash, hash::hash,

View File

@ -1,10 +1,13 @@
//! Durable transaction nonce helpers. //! Durable transaction nonce helpers.
pub use crate::nonblocking::nonce_utils::{ pub mod blockhash_query;
pub mod nonblocking;
pub use crate::nonblocking::{
account_identity_ok, data_from_account, data_from_state, state_from_account, Error, account_identity_ok, data_from_account, data_from_state, state_from_account, Error,
}; };
use { use {
crate::rpc_client::RpcClient, solana_rpc_client::rpc_client::RpcClient,
solana_sdk::{account::Account, commitment_config::CommitmentConfig, pubkey::Pubkey}, solana_sdk::{account::Account, commitment_config::CommitmentConfig, pubkey::Pubkey},
}; };

View File

@ -1,11 +1,12 @@
use { use {
crate::nonblocking::{nonce_utils, rpc_client::RpcClient}, crate::nonblocking,
clap::ArgMatches, clap::ArgMatches,
solana_clap_utils::{ solana_clap_utils::{
input_parsers::{pubkey_of, value_of}, input_parsers::{pubkey_of, value_of},
nonce::*, nonce::*,
offline::*, offline::*,
}, },
solana_rpc_client::nonblocking::rpc_client::RpcClient,
solana_sdk::{commitment_config::CommitmentConfig, hash::Hash, pubkey::Pubkey}, solana_sdk::{commitment_config::CommitmentConfig, hash::Hash, pubkey::Pubkey},
}; };
@ -30,9 +31,9 @@ impl Source {
} }
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
let data = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment) let data = nonblocking::get_account_with_commitment(rpc_client, pubkey, commitment)
.await .await
.and_then(|ref a| nonce_utils::data_from_account(a))?; .and_then(|ref a| nonblocking::data_from_account(a))?;
Ok(data.blockhash()) Ok(data.blockhash())
} }
} }
@ -48,9 +49,9 @@ impl Source {
Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment).await?, Self::Cluster => rpc_client.is_blockhash_valid(blockhash, commitment).await?,
Self::NonceAccount(ref pubkey) => { Self::NonceAccount(ref pubkey) => {
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
let _ = nonce_utils::get_account_with_commitment(rpc_client, pubkey, commitment) let _ = nonblocking::get_account_with_commitment(rpc_client, pubkey, commitment)
.await .await
.and_then(|ref a| nonce_utils::data_from_account(a))?; .and_then(|ref a| nonblocking::data_from_account(a))?;
true true
} }
}) })
@ -115,14 +116,14 @@ impl Default for BlockhashQuery {
mod tests { mod tests {
use { use {
super::*, super::*,
crate::{ crate::nonblocking::blockhash_query,
nonblocking::blockhash_query,
rpc_request::RpcRequest,
rpc_response::{Response, RpcBlockhash, RpcResponseContext},
},
clap::App, clap::App,
serde_json::{self, json}, serde_json::{self, json},
solana_account_decoder::{UiAccount, UiAccountEncoding}, solana_account_decoder::{UiAccount, UiAccountEncoding},
solana_rpc_client_api::{
request::RpcRequest,
response::{Response, RpcBlockhash, RpcResponseContext},
},
solana_sdk::{ solana_sdk::{
account::Account, account::Account,
fee_calculator::FeeCalculator, fee_calculator::FeeCalculator,

View File

@ -1,7 +1,9 @@
//! Durable transaction nonce helpers. //! Durable transaction nonce helpers.
pub mod blockhash_query;
use { use {
crate::nonblocking::rpc_client::RpcClient, solana_rpc_client::nonblocking::rpc_client::RpcClient,
solana_sdk::{ solana_sdk::{
account::{Account, ReadableAccount}, account::{Account, ReadableAccount},
account_utils::StateMut, account_utils::StateMut,
@ -97,10 +99,8 @@ pub fn account_identity_ok<T: ReadableAccount>(account: &T) -> Result<(), Error>
/// Determine if a nonce account is initialized: /// Determine if a nonce account is initialized:
/// ///
/// ```no_run /// ```no_run
/// use solana_client::nonblocking::{ /// use solana_rpc_client_nonce_utils::nonblocking;
/// rpc_client::RpcClient, /// use solana_rpc_client::nonblocking::rpc_client::RpcClient;
/// nonce_utils,
/// };
/// use solana_sdk::{ /// use solana_sdk::{
/// nonce::State, /// nonce::State,
/// pubkey::Pubkey, /// pubkey::Pubkey,
@ -116,7 +116,7 @@ pub fn account_identity_ok<T: ReadableAccount>(account: &T) -> Result<(), Error>
/// // Sign the tx with nonce_account's `blockhash` instead of the /// // Sign the tx with nonce_account's `blockhash` instead of the
/// // network's latest blockhash. /// // network's latest blockhash.
/// let nonce_account = client.get_account(nonce_account_pubkey).await?; /// let nonce_account = client.get_account(nonce_account_pubkey).await?;
/// let nonce_state = nonce_utils::state_from_account(&nonce_account)?; /// let nonce_state = nonblocking::state_from_account(&nonce_account)?;
/// ///
/// Ok(!matches!(nonce_state, State::Uninitialized)) /// Ok(!matches!(nonce_state, State::Uninitialized))
/// } /// }
@ -149,10 +149,8 @@ pub fn state_from_account<T: ReadableAccount + StateMut<Versions>>(
/// Create and sign a transaction with a durable nonce: /// Create and sign a transaction with a durable nonce:
/// ///
/// ```no_run /// ```no_run
/// use solana_client::nonblocking::{ /// use solana_rpc_client_nonce_utils::nonblocking;
/// rpc_client::RpcClient, /// use solana_rpc_client::nonblocking::rpc_client::RpcClient;
/// nonce_utils,
/// };
/// use solana_sdk::{ /// use solana_sdk::{
/// message::Message, /// message::Message,
/// pubkey::Pubkey, /// pubkey::Pubkey,
@ -201,7 +199,7 @@ pub fn state_from_account<T: ReadableAccount + StateMut<Versions>>(
/// // Sign the tx with nonce_account's `blockhash` instead of the /// // Sign the tx with nonce_account's `blockhash` instead of the
/// // network's latest blockhash. /// // network's latest blockhash.
/// let nonce_account = client.get_account(nonce_account_pubkey).await?; /// let nonce_account = client.get_account(nonce_account_pubkey).await?;
/// let nonce_data = nonce_utils::data_from_account(&nonce_account)?; /// let nonce_data = nonblocking::data_from_account(&nonce_account)?;
/// let blockhash = nonce_data.blockhash(); /// let blockhash = nonce_data.blockhash();
/// ///
/// tx.try_sign(&[payer], blockhash)?; /// tx.try_sign(&[payer], blockhash)?;

40
rpc-client/Cargo.toml Normal file
View File

@ -0,0 +1,40 @@
[package]
name = "solana-rpc-client"
version = "1.12.0"
description = "Solana RPC Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-rpc-client"
edition = "2021"
[dependencies]
async-trait = "0.1.57"
base64 = "0.13.0"
bincode = "1.3.3"
bs58 = "0.4.0"
indicatif = "0.17.0"
log = "0.4.17"
reqwest = { version = "0.11.11", default-features = false, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] }
semver = "1.0.13"
serde = "1.0.143"
serde_derive = "1.0.103"
serde_json = "1.0.83"
solana-account-decoder = { path = "../account-decoder", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.12.0" }
solana-version = { path = "../version", version = "=1.12.0" }
solana-vote-program = { path = "../programs/vote", version = "=1.12.0" }
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
assert_matches = "1.5.0"
crossbeam-channel = "0.5"
futures = "0.3"
jsonrpc-core = "18.0.0"
jsonrpc-http-server = "18.0.0"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@ -1,13 +1,7 @@
//! Nonblocking [`RpcSender`] over HTTP. //! Nonblocking [`RpcSender`] over HTTP.
use { use {
crate::{ crate::rpc_sender::*,
client_error::Result,
rpc_custom_error,
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData},
rpc_response::RpcSimulateTransactionResult,
rpc_sender::*,
},
async_trait::async_trait, async_trait::async_trait,
log::*, log::*,
reqwest::{ reqwest::{
@ -15,6 +9,13 @@ use {
header::{self, CONTENT_TYPE, RETRY_AFTER}, header::{self, CONTENT_TYPE, RETRY_AFTER},
StatusCode, StatusCode,
}, },
solana_rpc_client_api::{
client_error::Result,
custom_error,
error_object::RpcErrorObject,
request::{RpcError, RpcRequest, RpcResponseErrorData},
response::RpcSimulateTransactionResult,
},
std::{ std::{
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
@ -72,12 +73,6 @@ impl HttpSender {
} }
} }
#[derive(Deserialize, Debug)]
pub(crate) struct RpcErrorObject {
pub code: i64,
pub message: String,
}
struct StatsUpdater<'a> { struct StatsUpdater<'a> {
stats: &'a RwLock<RpcTransportStats>, stats: &'a RwLock<RpcTransportStats>,
request_start_time: Instant, request_start_time: Instant,
@ -169,7 +164,7 @@ impl RpcSender for HttpSender {
return match serde_json::from_value::<RpcErrorObject>(json["error"].clone()) { return match serde_json::from_value::<RpcErrorObject>(json["error"].clone()) {
Ok(rpc_error_object) => { Ok(rpc_error_object) => {
let data = match rpc_error_object.code { let data = match rpc_error_object.code {
rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE => { custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE => {
match serde_json::from_value::<RpcSimulateTransactionResult>(json["error"]["data"].clone()) { match serde_json::from_value::<RpcSimulateTransactionResult>(json["error"]["data"].clone()) {
Ok(data) => RpcResponseErrorData::SendTransactionPreflightFailure(data), Ok(data) => RpcResponseErrorData::SendTransactionPreflightFailure(data),
Err(err) => { Err(err) => {
@ -178,9 +173,9 @@ impl RpcSender for HttpSender {
} }
} }
}, },
rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY => { custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY => {
match serde_json::from_value::<rpc_custom_error::NodeUnhealthyErrorData>(json["error"]["data"].clone()) { match serde_json::from_value::<custom_error::NodeUnhealthyErrorData>(json["error"]["data"].clone()) {
Ok(rpc_custom_error::NodeUnhealthyErrorData {num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind}, Ok(custom_error::NodeUnhealthyErrorData {num_slots_behind}) => RpcResponseErrorData::NodeUnhealthy {num_slots_behind},
Err(_err) => { Err(_err) => {
RpcResponseErrorData::Empty RpcResponseErrorData::Empty
} }

15
rpc-client/src/lib.rs Normal file
View File

@ -0,0 +1,15 @@
#![allow(clippy::integer_arithmetic)]
pub mod http_sender;
pub mod mock_sender;
pub mod nonblocking;
pub mod rpc_client;
pub mod rpc_sender;
pub mod spinner;
pub mod mock_sender_for_cli {
/// Magic `SIGNATURE` value used by `solana-cli` unit tests.
/// Please don't use this constant.
pub const SIGNATURE: &str =
"43yNSFC6fYTuPgTNFFhF4axw7AfWxB2BPdurme8yrsWEYwm8299xh8n6TAHjGymiSub1XtyxTNyd9GBfY2hxoBw8";
}

View File

@ -1,11 +1,15 @@
//! A nonblocking [`RpcSender`] used for unit testing [`RpcClient`](crate::rpc_client::RpcClient). //! A nonblocking [`RpcSender`] used for unit testing [`RpcClient`](crate::rpc_client::RpcClient).
use { use {
crate::{ crate::rpc_sender::*,
async_trait::async_trait,
serde_json::{json, Number, Value},
solana_account_decoder::{UiAccount, UiAccountEncoding},
solana_rpc_client_api::{
client_error::Result, client_error::Result,
rpc_config::RpcBlockProductionConfig, config::RpcBlockProductionConfig,
rpc_request::RpcRequest, request::RpcRequest,
rpc_response::{ response::{
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash, Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash,
RpcConfirmedTransactionStatusWithSignature, RpcContactInfo, RpcFees, RpcIdentity, RpcConfirmedTransactionStatusWithSignature, RpcContactInfo, RpcFees, RpcIdentity,
RpcInflationGovernor, RpcInflationRate, RpcInflationReward, RpcKeyedAccount, RpcInflationGovernor, RpcInflationRate, RpcInflationReward, RpcKeyedAccount,
@ -13,11 +17,7 @@ use {
RpcStakeActivation, RpcSupply, RpcVersionInfo, RpcVoteAccountInfo, RpcStakeActivation, RpcSupply, RpcVersionInfo, RpcVoteAccountInfo,
RpcVoteAccountStatus, StakeActivationState, RpcVoteAccountStatus, StakeActivationState,
}, },
rpc_sender::*,
}, },
async_trait::async_trait,
serde_json::{json, Number, Value},
solana_account_decoder::{UiAccount, UiAccountEncoding},
solana_sdk::{ solana_sdk::{
account::Account, account::Account,
clock::{Slot, UnixTimestamp}, clock::{Slot, UnixTimestamp},

View File

@ -0,0 +1 @@
pub mod rpc_client;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
//! A transport for RPC calls. //! A transport for RPC calls.
use { use {
crate::{client_error::Result, rpc_request::RpcRequest},
async_trait::async_trait, async_trait::async_trait,
solana_rpc_client_api::{client_error::Result, request::RpcRequest},
std::time::Duration, std::time::Duration,
}; };

17
rpc-client/src/spinner.rs Normal file
View File

@ -0,0 +1,17 @@
//! Spinner creator
use {
indicatif::{ProgressBar, ProgressStyle},
std::time::Duration,
};
pub fn new_progress_bar() -> ProgressBar {
let progress_bar = ProgressBar::new(42);
progress_bar.set_style(
ProgressStyle::default_spinner()
.template("{spinner:.green} {wide_msg}")
.expect("ProgresStyle::template direct input to be correct"),
);
progress_bar.enable_steady_tick(Duration::from_millis(100));
progress_bar
}

View File

@ -4,6 +4,7 @@ pub mod max_slots;
pub mod optimistically_confirmed_bank_tracker; pub mod optimistically_confirmed_bank_tracker;
pub mod parsed_token_accounts; pub mod parsed_token_accounts;
pub mod rpc; pub mod rpc;
mod rpc_cache;
pub mod rpc_completed_slots_service; pub mod rpc_completed_slots_service;
pub mod rpc_health; pub mod rpc_health;
pub mod rpc_pubsub; pub mod rpc_pubsub;

View File

@ -3,7 +3,7 @@
use { use {
crate::{ crate::{
max_slots::MaxSlots, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank, max_slots::MaxSlots, optimistically_confirmed_bank_tracker::OptimisticallyConfirmedBank,
parsed_token_accounts::*, rpc_health::*, parsed_token_accounts::*, rpc_cache::LargestAccountsCache, rpc_health::*,
}, },
bincode::{config::Options, serialize}, bincode::{config::Options, serialize},
crossbeam_channel::{unbounded, Receiver, Sender}, crossbeam_channel::{unbounded, Receiver, Sender},
@ -16,7 +16,6 @@ use {
}, },
solana_client::{ solana_client::{
connection_cache::ConnectionCache, connection_cache::ConnectionCache,
rpc_cache::LargestAccountsCache,
rpc_config::*, rpc_config::*,
rpc_custom_error::RpcCustomError, rpc_custom_error::RpcCustomError,
rpc_deprecated_config::*, rpc_deprecated_config::*,

View File

@ -1,5 +1,5 @@
use { use {
crate::{rpc_config::RpcLargestAccountsFilter, rpc_response::RpcAccountBalance}, solana_client::{rpc_config::RpcLargestAccountsFilter, rpc_response::RpcAccountBalance},
std::{ std::{
collections::HashMap, collections::HashMap,
time::{Duration, SystemTime}, time::{Duration, SystemTime},
@ -20,14 +20,14 @@ struct LargestAccountsCacheValue {
} }
impl LargestAccountsCache { impl LargestAccountsCache {
pub fn new(duration: u64) -> Self { pub(crate) fn new(duration: u64) -> Self {
Self { Self {
duration, duration,
cache: HashMap::new(), cache: HashMap::new(),
} }
} }
pub fn get_largest_accounts( pub(crate) fn get_largest_accounts(
&self, &self,
filter: &Option<RpcLargestAccountsFilter>, filter: &Option<RpcLargestAccountsFilter>,
) -> Option<(u64, Vec<RpcAccountBalance>)> { ) -> Option<(u64, Vec<RpcAccountBalance>)> {
@ -41,7 +41,7 @@ impl LargestAccountsCache {
}) })
} }
pub fn set_largest_accounts( pub(crate) fn set_largest_accounts(
&mut self, &mut self,
filter: &Option<RpcLargestAccountsFilter>, filter: &Option<RpcLargestAccountsFilter>,
slot: u64, slot: u64,

View File

@ -9,6 +9,7 @@ use {
rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_deprecated_v1_9::*, rpc_accounts::*, rpc_bank::*, rpc_deprecated_v1_7::*, rpc_deprecated_v1_9::*,
rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *, rpc_full::*, rpc_minimal::*, rpc_obsolete_v1_7::*, *,
}, },
rpc_cache::LargestAccountsCache,
rpc_health::*, rpc_health::*,
}, },
crossbeam_channel::unbounded, crossbeam_channel::unbounded,
@ -18,7 +19,7 @@ use {
RequestMiddlewareAction, ServerBuilder, RequestMiddlewareAction, ServerBuilder,
}, },
regex::Regex, regex::Regex,
solana_client::{connection_cache::ConnectionCache, rpc_cache::LargestAccountsCache}, solana_client::connection_cache::ConnectionCache,
solana_gossip::cluster_info::ClusterInfo, solana_gossip::cluster_info::ClusterInfo,
solana_ledger::{ solana_ledger::{
bigtable_upload::ConfirmedBlockUploadConfig, bigtable_upload::ConfirmedBlockUploadConfig,

25
thin-client/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
name = "solana-thin-client"
version = "1.12.0"
description = "Solana Thin Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-thin-client"
edition = "2021"
[dependencies]
bincode = "1.3.3"
log = "0.4.17"
solana-rpc-client = { path = "../rpc-client", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-tpu-client = { path = "../tpu-client", version = "=1.12.0" }
[dev-dependencies]
rayon = "1.5.3"
solana-logger = { path = "../logger", version = "=1.12.0" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

3
thin-client/src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
#![allow(clippy::integer_arithmetic)]
pub mod thin_client;

View File

@ -4,12 +4,9 @@
//! unstable and may change in future releases. //! unstable and may change in future releases.
use { use {
crate::{
connection_cache::ConnectionCache, rpc_client::RpcClient,
rpc_config::RpcProgramAccountsConfig, rpc_response::Response,
tpu_connection::TpuConnection,
},
log::*, log::*,
solana_rpc_client::rpc_client::RpcClient,
solana_rpc_client_api::{config::RpcProgramAccountsConfig, response::Response},
solana_sdk::{ solana_sdk::{
account::Account, account::Account,
client::{AsyncClient, Client, SyncClient}, client::{AsyncClient, Client, SyncClient},
@ -28,6 +25,7 @@ use {
transaction::{self, Transaction, VersionedTransaction}, transaction::{self, Transaction, VersionedTransaction},
transport::Result as TransportResult, transport::Result as TransportResult,
}, },
solana_tpu_client::{connection_cache::ConnectionCache, tpu_connection::TpuConnection},
std::{ std::{
io, io,
net::SocketAddr, net::SocketAddr,

2
tpu-client/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target/
/farf/

48
tpu-client/Cargo.toml Normal file
View File

@ -0,0 +1,48 @@
[package]
name = "solana-tpu-client"
version = "1.12.0"
description = "Solana TPU Client"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
documentation = "https://docs.rs/solana-tpu-client"
edition = "2021"
[dependencies]
async-mutex = "1.4.0"
async-trait = "0.1.57"
bincode = "1.3.3"
enum_dispatch = "0.3.8"
futures = "0.3"
futures-util = "0.3.21"
indexmap = "1.9.1"
indicatif = "0.17.0"
itertools = "0.10.2"
lazy_static = "1.4.0"
log = "0.4.17"
quinn = "0.8.4"
quinn-proto = "0.8.4"
quinn-udp = "0.1.3"
rand = "0.7.0"
rayon = "1.5.3"
rustls = { version = "0.20.6", features = ["dangerous_configuration"] }
solana-measure = { path = "../measure", version = "=1.12.0" }
solana-metrics = { path = "../metrics", version = "=1.12.0" }
solana-net-utils = { path = "../net-utils", version = "=1.12.0" }
solana-pubsub-client = { path = "../pubsub-client", version = "=1.12.0" }
solana-rpc-client = { path = "../rpc-client", version = "=1.12.0" }
solana-rpc-client-api = { path = "../rpc-client-api", version = "=1.12.0" }
solana-sdk = { path = "../sdk", version = "=1.12.0" }
solana-streamer = { path = "../streamer", version = "=1.12.0" }
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
crossbeam-channel = "0.5"
rand_chacha = "0.2.2"
solana-logger = { path = "../logger", version = "=1.12.0" }
solana-perf = { path = "../perf", version = "=1.12.0" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

11
tpu-client/src/lib.rs Normal file
View File

@ -0,0 +1,11 @@
#![allow(clippy::integer_arithmetic)]
pub mod connection_cache;
pub mod nonblocking;
pub mod quic_client;
pub mod tpu_client;
pub mod tpu_connection;
pub mod udp_client;
#[macro_use]
extern crate solana_metrics;

View File

@ -0,0 +1,4 @@
pub mod quic_client;
pub mod tpu_client;
pub mod tpu_connection;
pub mod udp_client;

View File

@ -3,8 +3,8 @@
//! server's flow control. //! server's flow control.
use { use {
crate::{ crate::{
client_error::ClientErrorKind, connection_cache::ConnectionCacheStats, connection_cache::ConnectionCacheStats, nonblocking::tpu_connection::TpuConnection,
nonblocking::tpu_connection::TpuConnection, tpu_connection::ClientStats, tpu_connection::ClientStats,
}, },
async_mutex::Mutex, async_mutex::Mutex,
async_trait::async_trait, async_trait::async_trait,
@ -17,6 +17,7 @@ use {
}, },
solana_measure::measure::Measure, solana_measure::measure::Measure,
solana_net_utils::VALIDATOR_PORT_RANGE, solana_net_utils::VALIDATOR_PORT_RANGE,
solana_rpc_client_api::client_error::ErrorKind as ClientErrorKind,
solana_sdk::{ solana_sdk::{
quic::{ quic::{
QUIC_CONNECTION_HANDSHAKE_TIMEOUT_MS, QUIC_KEEP_ALIVE_MS, QUIC_MAX_TIMEOUT_MS, QUIC_CONNECTION_HANDSHAKE_TIMEOUT_MS, QUIC_KEEP_ALIVE_MS, QUIC_MAX_TIMEOUT_MS,
@ -82,6 +83,12 @@ pub enum QuicError {
ConnectError(#[from] ConnectError), ConnectError(#[from] ConnectError),
} }
impl From<QuicError> for ClientErrorKind {
fn from(quic_error: QuicError) -> Self {
Self::Custom(format!("{:?}", quic_error))
}
}
impl QuicLazyInitializedEndpoint { impl QuicLazyInitializedEndpoint {
pub fn new(client_certificate: Arc<QuicClientCertificate>) -> Self { pub fn new(client_certificate: Arc<QuicClientCertificate>) -> Self {
Self { Self {
@ -439,7 +446,8 @@ impl QuicClient {
T: AsRef<[u8]>, T: AsRef<[u8]>,
{ {
self._send_buffer(data.as_ref(), stats, connection_stats) self._send_buffer(data.as_ref(), stats, connection_stats)
.await?; .await
.map_err(Into::<ClientErrorKind>::into)?;
Ok(()) Ok(())
} }
@ -483,7 +491,8 @@ impl QuicClient {
} }
let connection = self let connection = self
._send_buffer(buffers[0].as_ref(), stats, connection_stats) ._send_buffer(buffers[0].as_ref(), stats, connection_stats)
.await?; .await
.map_err(Into::<ClientErrorKind>::into)?;
// Used to avoid dereferencing the Arc multiple times below // Used to avoid dereferencing the Arc multiple times below
// by just getting a reference to the NewConnection once // by just getting a reference to the NewConnection once
@ -504,7 +513,10 @@ impl QuicClient {
.collect(); .collect();
for f in futures { for f in futures {
f.await.into_iter().try_for_each(|res| res)?; f.await
.into_iter()
.try_for_each(|res| res)
.map_err(Into::<ClientErrorKind>::into)?;
} }
Ok(()) Ok(())
} }

View File

@ -1,15 +1,7 @@
use { use {
crate::{ crate::{
client_error::{ClientError, Result as ClientResult},
connection_cache::ConnectionCache, connection_cache::ConnectionCache,
nonblocking::{ nonblocking::tpu_connection::TpuConnection,
pubsub_client::{PubsubClient, PubsubClientError},
rpc_client::RpcClient,
tpu_connection::TpuConnection,
},
rpc_request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
rpc_response::{RpcContactInfo, SlotUpdate},
spinner,
tpu_client::{ tpu_client::{
RecentLeaderSlots, TpuClientConfig, MAX_FANOUT_SLOTS, SEND_TRANSACTION_INTERVAL, RecentLeaderSlots, TpuClientConfig, MAX_FANOUT_SLOTS, SEND_TRANSACTION_INTERVAL,
TRANSACTION_RESEND_INTERVAL, TRANSACTION_RESEND_INTERVAL,
@ -17,7 +9,15 @@ use {
}, },
bincode::serialize, bincode::serialize,
futures_util::{future::join_all, stream::StreamExt}, futures_util::{future::join_all, stream::StreamExt},
indicatif::ProgressBar,
log::*, log::*,
solana_pubsub_client::nonblocking::pubsub_client::{PubsubClient, PubsubClientError},
solana_rpc_client::{nonblocking::rpc_client::RpcClient, spinner},
solana_rpc_client_api::{
client_error::{Error as ClientError, Result as ClientResult},
request::MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS,
response::{RpcContactInfo, SlotUpdate},
},
solana_sdk::{ solana_sdk::{
clock::Slot, clock::Slot,
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
@ -366,7 +366,7 @@ impl TpuClient {
if !self.send_transaction(transaction).await { if !self.send_transaction(transaction).await {
let _result = self.rpc_client.send_transaction(transaction).await.ok(); let _result = self.rpc_client.send_transaction(transaction).await.ok();
} }
spinner::set_message_for_confirmed_transactions( set_message_for_confirmed_transactions(
&progress_bar, &progress_bar,
confirmed_transactions, confirmed_transactions,
total_transactions, total_transactions,
@ -381,7 +381,7 @@ impl TpuClient {
// Wait for the next block before checking for transaction statuses // Wait for the next block before checking for transaction statuses
let mut block_height_refreshes = 10; let mut block_height_refreshes = 10;
spinner::set_message_for_confirmed_transactions( set_message_for_confirmed_transactions(
&progress_bar, &progress_bar,
confirmed_transactions, confirmed_transactions,
total_transactions, total_transactions,
@ -430,7 +430,7 @@ impl TpuClient {
} }
} }
} }
spinner::set_message_for_confirmed_transactions( set_message_for_confirmed_transactions(
&progress_bar, &progress_bar,
confirmed_transactions, confirmed_transactions,
total_transactions, total_transactions,
@ -666,3 +666,26 @@ async fn maybe_fetch_cache_info(
maybe_slot_leaders, maybe_slot_leaders,
} }
} }
fn set_message_for_confirmed_transactions(
progress_bar: &ProgressBar,
confirmed_transactions: u32,
total_transactions: usize,
block_height: Option<u64>,
last_valid_block_height: u64,
status: &str,
) {
progress_bar.set_message(format!(
"{:>5.1}% | {:<40}{}",
confirmed_transactions as f64 * 100. / total_transactions as f64,
status,
match block_height {
Some(block_height) => format!(
" [block height {}; re-sign in {} blocks]",
block_height,
last_valid_block_height.saturating_sub(block_height),
),
None => String::new(),
},
));
}

View File

@ -2,8 +2,9 @@ pub use crate::nonblocking::tpu_client::TpuSenderError;
use { use {
crate::{ crate::{
connection_cache::ConnectionCache, connection_cache::ConnectionCache,
nonblocking::tpu_client::TpuClient as NonblockingTpuClient, rpc_client::RpcClient, nonblocking::tpu_client::TpuClient as NonblockingTpuClient,
}, },
solana_rpc_client::rpc_client::RpcClient,
solana_sdk::{ solana_sdk::{
clock::Slot, clock::Slot,
message::Message, message::Message,

View File

@ -2,13 +2,13 @@
mod tests { mod tests {
use { use {
crossbeam_channel::{unbounded, Receiver}, crossbeam_channel::{unbounded, Receiver},
solana_client::{
connection_cache::ConnectionCacheStats,
nonblocking::quic_client::QuicLazyInitializedEndpoint,
},
solana_perf::packet::PacketBatch, solana_perf::packet::PacketBatch,
solana_sdk::{packet::PACKET_DATA_SIZE, signature::Keypair}, solana_sdk::{packet::PACKET_DATA_SIZE, signature::Keypair},
solana_streamer::{quic::StreamStats, streamer::StakedNodes}, solana_streamer::{quic::StreamStats, streamer::StakedNodes},
solana_tpu_client::{
connection_cache::ConnectionCacheStats,
nonblocking::quic_client::QuicLazyInitializedEndpoint,
},
std::{ std::{
net::{IpAddr, SocketAddr, UdpSocket}, net::{IpAddr, SocketAddr, UdpSocket},
sync::{ sync::{
@ -62,7 +62,7 @@ mod tests {
#[test] #[test]
fn test_quic_client_multiple_writes() { fn test_quic_client_multiple_writes() {
use solana_client::{quic_client::QuicTpuConnection, tpu_connection::TpuConnection}; use solana_tpu_client::{quic_client::QuicTpuConnection, tpu_connection::TpuConnection};
solana_logger::setup(); solana_logger::setup();
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
let staked_nodes = Arc::new(RwLock::new(StakedNodes::default())); let staked_nodes = Arc::new(RwLock::new(StakedNodes::default()));
@ -105,7 +105,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_nonblocking_quic_client_multiple_writes() { async fn test_nonblocking_quic_client_multiple_writes() {
use solana_client::nonblocking::{ use solana_tpu_client::nonblocking::{
quic_client::QuicTpuConnection, tpu_connection::TpuConnection, quic_client::QuicTpuConnection, tpu_connection::TpuConnection,
}; };
solana_logger::setup(); solana_logger::setup();