diff --git a/bench-tps/Cargo.toml b/bench-tps/Cargo.toml index 9c86da1ee..1e4313c1b 100644 --- a/bench-tps/Cargo.toml +++ b/bench-tps/Cargo.toml @@ -12,6 +12,7 @@ clap = "2.32.0" rayon = "1.0.3" serde_json = "1.0.39" solana = { path = "../core", version = "0.13.0" } +solana-client = { path = "../client", version = "0.13.0" } solana-drone = { path = "../drone", version = "0.13.0" } solana-logger = { path = "../logger", version = "0.13.0" } solana-metrics = { path = "../metrics", version = "0.13.0" } diff --git a/bench-tps/src/bench.rs b/bench-tps/src/bench.rs index 2970614b9..880d8a58b 100644 --- a/bench-tps/src/bench.rs +++ b/bench-tps/src/bench.rs @@ -1,9 +1,9 @@ use solana_metrics; use rayon::prelude::*; -use solana::client::mk_client; +use solana::cluster_client::mk_client; use solana::contact_info::ContactInfo; -use solana::thin_client::ThinClient; +use solana_client::thin_client::ThinClient; use solana_drone::drone::request_airdrop_transaction; use solana_metrics::influxdb; use solana_sdk::hash::Hash; diff --git a/bench-tps/src/main.rs b/bench-tps/src/main.rs index a339db3dd..8ff403933 100644 --- a/bench-tps/src/main.rs +++ b/bench-tps/src/main.rs @@ -2,7 +2,7 @@ mod bench; mod cli; use crate::bench::*; -use solana::client::mk_client; +use solana::cluster_client::mk_client; use solana::gen_keys::GenKeys; use solana::gossip_service::discover; use solana_metrics; diff --git a/core/Cargo.toml b/core/Cargo.toml index dca75e2f3..be0c55256 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -39,13 +39,13 @@ nix = "0.13.0" rand = "0.6.5" rand_chacha = "0.1.1" rayon = "1.0.0" -reqwest = "0.9.11" ring = "0.13.2" rocksdb = "0.11.0" serde = "1.0.89" serde_derive = "1.0.88" serde_json = "1.0.39" solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" } +solana-client = { path = "../client", version = "0.13.0" } solana-drone = { path = "../drone", version = "0.13.0" } solana-logger = { path = "../logger", version = "0.13.0" } solana-metrics = { path = "../metrics", version = "0.13.0" } @@ -65,4 +65,3 @@ hex-literal = "0.1.3" matches = "0.1.6" solana-vote-program = { path = "../programs/vote", version = "0.13.0" } solana-budget-program = { path = "../programs/budget", version = "0.13.0" } - diff --git a/core/src/client.rs b/core/src/cluster_client.rs similarity index 92% rename from core/src/client.rs rename to core/src/cluster_client.rs index 033530d52..edba859b4 100644 --- a/core/src/client.rs +++ b/core/src/cluster_client.rs @@ -1,6 +1,6 @@ use crate::cluster_info::FULLNODE_PORT_RANGE; use crate::contact_info::ContactInfo; -use crate::thin_client::ThinClient; +use solana_client::thin_client::ThinClient; use std::time::Duration; pub fn mk_client(r: &ContactInfo) -> ThinClient { diff --git a/core/src/cluster_tests.rs b/core/src/cluster_tests.rs index f9b56be3f..4cddb6a59 100644 --- a/core/src/cluster_tests.rs +++ b/core/src/cluster_tests.rs @@ -3,7 +3,7 @@ use crate::blocktree::Blocktree; /// /// All tests must start from an entry point and a funding keypair and /// discover the rest of the network. -use crate::client::mk_client; +use crate::cluster_client::mk_client; use crate::contact_info::ContactInfo; use crate::entry::{Entry, EntrySlice}; use crate::gossip_service::discover; diff --git a/core/src/fullnode.rs b/core/src/fullnode.rs index ef9ee0fd8..d1235a005 100644 --- a/core/src/fullnode.rs +++ b/core/src/fullnode.rs @@ -372,6 +372,36 @@ pub fn make_active_set_entries( (entries, voting_keypair) } +pub fn new_fullnode_for_tests() -> (Fullnode, ContactInfo, Keypair, String) { + use crate::blocktree::create_new_tmp_ledger; + use crate::cluster_info::Node; + + let node_keypair = Arc::new(Keypair::new()); + let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey()); + let contact_info = node.info.clone(); + + let (mut genesis_block, mint_keypair) = + GenesisBlock::new_with_leader(10_000, &contact_info.id, 42); + genesis_block + .native_programs + .push(("solana_budget_program".to_string(), solana_budget_api::id())); + + let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block); + + let voting_keypair = Keypair::new(); + let node = Fullnode::new( + node, + &node_keypair, + &ledger_path, + &voting_keypair.pubkey(), + voting_keypair, + None, + &FullnodeConfig::default(), + ); + + (node, contact_info, mint_keypair, ledger_path) +} + #[cfg(test)] mod tests { use super::*; diff --git a/core/src/lib.rs b/core/src/lib.rs index f55981b38..79545c668 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -3,7 +3,6 @@ //! [Fullnode](server/struct.Fullnode.html)) as well as hooks to GPU implementations of its most //! paralellizable components (i.e. [SigVerify](sigverify/index.html)). It also includes //! command-line tools to spin up fullnodes and a Rust library -//! (see [ThinClient](thin_client/struct.ThinClient.html)) to interact with them. //! pub mod bank_forks; @@ -14,7 +13,7 @@ pub mod broadcast_stage; pub mod chacha; #[cfg(all(feature = "chacha", feature = "cuda"))] pub mod chacha_cuda; -pub mod client; +pub mod cluster_client; pub mod cluster_info_vote_listener; #[macro_use] pub mod contact_info; @@ -57,10 +56,8 @@ pub mod replicator; pub mod result; pub mod retransmit_stage; pub mod rpc; -pub mod rpc_mock; pub mod rpc_pubsub; pub mod rpc_pubsub_service; -pub mod rpc_request; pub mod rpc_service; pub mod rpc_status; pub mod rpc_subscriptions; @@ -71,7 +68,6 @@ pub mod staking_utils; pub mod storage_stage; pub mod streamer; pub mod test_tx; -pub mod thin_client; pub mod tpu; pub mod tvu; pub mod voting_keypair; diff --git a/core/src/local_cluster.rs b/core/src/local_cluster.rs index 10b8f2e08..d83fcee61 100644 --- a/core/src/local_cluster.rs +++ b/core/src/local_cluster.rs @@ -1,12 +1,11 @@ use crate::blocktree::{create_new_tmp_ledger, tmp_copy_blocktree}; -use crate::client::mk_client; +use crate::cluster_client::mk_client; use crate::cluster_info::Node; use crate::contact_info::ContactInfo; use crate::fullnode::{Fullnode, FullnodeConfig}; use crate::gossip_service::discover; use crate::service::Service; -use crate::thin_client::retry_get_balance; -use crate::thin_client::ThinClient; +use solana_client::thin_client::{retry_get_balance, ThinClient}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; diff --git a/core/src/replicator.rs b/core/src/replicator.rs index ce8f9a7d5..1b2b5ee8e 100644 --- a/core/src/replicator.rs +++ b/core/src/replicator.rs @@ -3,19 +3,19 @@ use crate::blocktree::Blocktree; use crate::blocktree_processor; #[cfg(feature = "chacha")] use crate::chacha::{chacha_cbc_encrypt_ledger, CHACHA_BLOCK_SIZE}; -use crate::client::mk_client; +use crate::cluster_client::mk_client; use crate::cluster_info::{ClusterInfo, Node}; use crate::contact_info::ContactInfo; use crate::gossip_service::GossipService; use crate::result::Result; -use crate::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; use crate::service::Service; use crate::storage_stage::{get_segment_from_entry, ENTRIES_PER_SEGMENT}; use crate::streamer::BlobReceiver; -use crate::thin_client::{retry_get_balance, ThinClient}; use crate::window_service::WindowService; use rand::thread_rng; use rand::Rng; +use solana_client::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; +use solana_client::thin_client::{retry_get_balance, ThinClient}; use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::{Hash, Hasher}; diff --git a/core/src/rpc_mock.rs b/core/src/rpc_mock.rs deleted file mode 100644 index eafd792ec..000000000 --- a/core/src/rpc_mock.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Implementation of RpcRequestHandler trait for testing Rpc requests without i/o - -use crate::rpc_request::{RpcRequest, RpcRequestHandler}; -use serde_json::{Number, Value}; -use solana_sdk::hash::Hash; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::system_transaction::SystemTransaction; -use solana_sdk::transaction::Transaction; -use std::error; -use std::io::{Error, ErrorKind}; -use std::net::SocketAddr; - -pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8"; -pub const SIGNATURE: &str = - "43yNSFC6fYTuPgTNFFhF4axw7AfWxB2BPdurme8yrsWEYwm8299xh8n6TAHjGymiSub1XtyxTNyd9GBfY2hxoBw8"; - -#[derive(Clone)] -pub struct MockRpcClient { - pub addr: String, -} - -impl MockRpcClient { - pub fn new(addr: String) -> Self { - MockRpcClient { addr } - } - - pub fn retry_get_balance( - &self, - id: u64, - pubkey: &Pubkey, - retries: usize, - ) -> Result, Box> { - let params = json!([format!("{}", pubkey)]); - let res = self - .retry_make_rpc_request(id, &RpcRequest::GetBalance, Some(params), retries)? - .as_u64(); - Ok(res) - } - - pub fn retry_make_rpc_request( - &self, - _id: u64, - request: &RpcRequest, - params: Option, - mut _retries: usize, - ) -> Result> { - if self.addr == "fails" { - return Ok(Value::Null); - } - let val = match request { - RpcRequest::ConfirmTransaction => { - if let Some(Value::Array(param_array)) = params { - if let Value::String(param_string) = ¶m_array[0] { - Value::Bool(param_string == SIGNATURE) - } else { - Value::Null - } - } else { - Value::Null - } - } - RpcRequest::GetBalance => { - let n = if self.addr == "airdrop" { 0 } else { 50 }; - Value::Number(Number::from(n)) - } - RpcRequest::GetRecentBlockhash => Value::String(PUBKEY.to_string()), - RpcRequest::GetSignatureStatus => { - let str = if self.addr == "account_in_use" { - "AccountInUse" - } else if self.addr == "bad_sig_status" { - "Nonexistent" - } else { - "Confirmed" - }; - Value::String(str.to_string()) - } - RpcRequest::GetTransactionCount => Value::Number(Number::from(1234)), - RpcRequest::SendTransaction => Value::String(SIGNATURE.to_string()), - _ => Value::Null, - }; - Ok(val) - } -} - -impl RpcRequestHandler for MockRpcClient { - fn make_rpc_request( - &self, - id: u64, - request: RpcRequest, - params: Option, - ) -> Result> { - self.retry_make_rpc_request(id, &request, params, 0) - } -} - -pub fn request_airdrop_transaction( - _drone_addr: &SocketAddr, - _id: &Pubkey, - lamports: u64, - _blockhash: Hash, -) -> Result { - if lamports == 0 { - Err(Error::new(ErrorKind::Other, "Airdrop failed"))? - } - let key = Keypair::new(); - let to = Keypair::new().pubkey(); - let blockhash = Hash::default(); - let tx = SystemTransaction::new_account(&key, &to, lamports, blockhash, 0); - Ok(tx) -} diff --git a/core/src/rpc_request.rs b/core/src/rpc_request.rs deleted file mode 100644 index 82af7181a..000000000 --- a/core/src/rpc_request.rs +++ /dev/null @@ -1,330 +0,0 @@ -use reqwest; -use reqwest::header::CONTENT_TYPE; -use serde_json::{self, Value}; -use solana_sdk::timing::{DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND}; -use std::net::SocketAddr; -use std::thread::sleep; -use std::time::Duration; -use std::{error, fmt}; - -use solana_sdk::pubkey::Pubkey; - -#[derive(Clone)] -pub struct RpcClient { - pub client: reqwest::Client, - pub addr: String, -} - -impl RpcClient { - pub fn new(addr: String) -> Self { - RpcClient { - client: reqwest::Client::new(), - addr, - } - } - - pub fn new_with_timeout(addr: SocketAddr, timeout: Duration) -> Self { - let addr = get_rpc_request_str(addr, false); - let client = reqwest::Client::builder() - .timeout(timeout) - .build() - .expect("build rpc client"); - RpcClient { client, addr } - } - - pub fn new_from_socket(addr: SocketAddr) -> Self { - Self::new(get_rpc_request_str(addr, false)) - } - - pub fn retry_get_balance( - &self, - id: u64, - pubkey: &Pubkey, - retries: usize, - ) -> Result, Box> { - let params = json!([format!("{}", pubkey)]); - let res = self - .retry_make_rpc_request(id, &RpcRequest::GetBalance, Some(params), retries)? - .as_u64(); - Ok(res) - } - - pub fn retry_make_rpc_request( - &self, - id: u64, - request: &RpcRequest, - params: Option, - mut retries: usize, - ) -> Result> { - let request_json = request.build_request_json(id, params); - - loop { - match self - .client - .post(&self.addr) - .header(CONTENT_TYPE, "application/json") - .body(request_json.to_string()) - .send() - { - Ok(mut response) => { - let json: Value = serde_json::from_str(&response.text()?)?; - if json["error"].is_object() { - Err(RpcError::RpcRequestError(format!( - "RPC Error response: {}", - serde_json::to_string(&json["error"]).unwrap() - )))? - } - return Ok(json["result"].clone()); - } - Err(e) => { - info!( - "make_rpc_request() failed, {} retries left: {:?}", - retries, e - ); - if retries == 0 { - Err(e)?; - } - retries -= 1; - - // Sleep for approximately half a slot - sleep(Duration::from_millis( - 500 * DEFAULT_TICKS_PER_SLOT / NUM_TICKS_PER_SECOND, - )); - } - } - } - } -} - -pub fn get_rpc_request_str(rpc_addr: SocketAddr, tls: bool) -> String { - if tls { - format!("https://{}", rpc_addr) - } else { - format!("http://{}", rpc_addr) - } -} - -pub trait RpcRequestHandler { - fn make_rpc_request( - &self, - id: u64, - request: RpcRequest, - params: Option, - ) -> Result>; -} - -impl RpcRequestHandler for RpcClient { - fn make_rpc_request( - &self, - id: u64, - request: RpcRequest, - params: Option, - ) -> Result> { - self.retry_make_rpc_request(id, &request, params, 0) - } -} - -#[derive(Debug, PartialEq)] -pub enum RpcRequest { - ConfirmTransaction, - GetAccountInfo, - GetBalance, - GetRecentBlockhash, - GetSignatureStatus, - GetTransactionCount, - RequestAirdrop, - SendTransaction, - RegisterNode, - SignVote, - DeregisterNode, - GetStorageBlockhash, - GetStorageEntryHeight, - GetStoragePubkeysForEntryHeight, - FullnodeExit, -} - -impl RpcRequest { - fn build_request_json(&self, id: u64, params: Option) -> Value { - let jsonrpc = "2.0"; - let method = match self { - RpcRequest::ConfirmTransaction => "confirmTransaction", - RpcRequest::GetAccountInfo => "getAccountInfo", - RpcRequest::GetBalance => "getBalance", - RpcRequest::GetRecentBlockhash => "getRecentBlockhash", - RpcRequest::GetSignatureStatus => "getSignatureStatus", - RpcRequest::GetTransactionCount => "getTransactionCount", - RpcRequest::RequestAirdrop => "requestAirdrop", - RpcRequest::SendTransaction => "sendTransaction", - RpcRequest::RegisterNode => "registerNode", - RpcRequest::SignVote => "signVote", - RpcRequest::DeregisterNode => "deregisterNode", - RpcRequest::GetStorageBlockhash => "getStorageBlockhash", - RpcRequest::GetStorageEntryHeight => "getStorageEntryHeight", - RpcRequest::GetStoragePubkeysForEntryHeight => "getStoragePubkeysForEntryHeight", - RpcRequest::FullnodeExit => "fullnodeExit", - }; - let mut request = json!({ - "jsonrpc": jsonrpc, - "id": id, - "method": method, - }); - if let Some(param_string) = params { - request["params"] = param_string; - } - request - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum RpcError { - RpcRequestError(String), -} - -impl fmt::Display for RpcError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "invalid") - } -} - -impl error::Error for RpcError { - fn description(&self) -> &str { - "invalid" - } - - fn cause(&self) -> Option<&dyn error::Error> { - // Generic error, underlying cause isn't tracked. - None - } -} - -#[cfg(test)] -mod tests { - use super::*; - use jsonrpc_core::{Error, IoHandler, Params}; - use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder}; - use serde_json::Number; - use std::net::Ipv4Addr; - use std::sync::mpsc::channel; - use std::thread; - - #[test] - fn test_build_request_json() { - let test_request = RpcRequest::GetAccountInfo; - let addr = json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]); - let request = test_request.build_request_json(1, Some(addr.clone())); - assert_eq!(request["method"], "getAccountInfo"); - assert_eq!(request["params"], addr,); - - let test_request = RpcRequest::GetBalance; - let request = test_request.build_request_json(1, Some(addr)); - assert_eq!(request["method"], "getBalance"); - - let test_request = RpcRequest::GetRecentBlockhash; - let request = test_request.build_request_json(1, None); - assert_eq!(request["method"], "getRecentBlockhash"); - - let test_request = RpcRequest::GetTransactionCount; - let request = test_request.build_request_json(1, None); - assert_eq!(request["method"], "getTransactionCount"); - - let test_request = RpcRequest::RequestAirdrop; - let request = test_request.build_request_json(1, None); - assert_eq!(request["method"], "requestAirdrop"); - - let test_request = RpcRequest::SendTransaction; - let request = test_request.build_request_json(1, None); - assert_eq!(request["method"], "sendTransaction"); - } - #[test] - fn test_make_rpc_request() { - let (sender, receiver) = channel(); - thread::spawn(move || { - let rpc_addr = socketaddr!(0, 0); - let mut io = IoHandler::default(); - // Successful request - io.add_method("getBalance", |_params: Params| { - Ok(Value::Number(Number::from(50))) - }); - // Failed request - io.add_method("getRecentBlockhash", |params: Params| { - if params != Params::None { - Err(Error::invalid_request()) - } else { - Ok(Value::String( - "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx".to_string(), - )) - } - }); - - let server = ServerBuilder::new(io) - .threads(1) - .cors(DomainsValidation::AllowOnly(vec![ - AccessControlAllowOrigin::Any, - ])) - .start_http(&rpc_addr) - .expect("Unable to start RPC server"); - sender.send(*server.address()).unwrap(); - server.wait(); - }); - - let rpc_addr = receiver.recv().unwrap(); - let rpc_client = RpcClient::new_from_socket(rpc_addr); - - let balance = rpc_client.make_rpc_request( - 1, - RpcRequest::GetBalance, - Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"])), - ); - assert_eq!(balance.unwrap().as_u64().unwrap(), 50); - - let blockhash = rpc_client.make_rpc_request(2, RpcRequest::GetRecentBlockhash, None); - assert_eq!( - blockhash.unwrap().as_str().unwrap(), - "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx" - ); - - // Send erroneous parameter - let blockhash = - rpc_client.make_rpc_request(3, RpcRequest::GetRecentBlockhash, Some(json!("paramter"))); - assert_eq!(blockhash.is_err(), true); - } - - #[test] - fn test_retry_make_rpc_request() { - solana_logger::setup(); - let (sender, receiver) = channel(); - thread::spawn(move || { - // 1. Pick a random port - // 2. Tell the client to start using it - // 3. Delay for 1.5 seconds before starting the server to ensure the client will fail - // and need to retry - let rpc_addr = socketaddr!(0, 4242); - sender.send(rpc_addr.clone()).unwrap(); - sleep(Duration::from_millis(1500)); - - let mut io = IoHandler::default(); - io.add_method("getBalance", move |_params: Params| { - Ok(Value::Number(Number::from(5))) - }); - let server = ServerBuilder::new(io) - .threads(1) - .cors(DomainsValidation::AllowOnly(vec![ - AccessControlAllowOrigin::Any, - ])) - .start_http(&rpc_addr) - .expect("Unable to start RPC server"); - server.wait(); - }); - - let rpc_addr = receiver.recv().unwrap(); - let rpc_client = RpcClient::new_from_socket(rpc_addr); - - let balance = rpc_client.retry_make_rpc_request( - 1, - &RpcRequest::GetBalance, - Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"])), - 10, - ); - assert_eq!(balance.unwrap().as_u64().unwrap(), 5); - } -} diff --git a/core/src/storage_stage.rs b/core/src/storage_stage.rs index 44694ea32..84fa81cd5 100644 --- a/core/src/storage_stage.rs +++ b/core/src/storage_stage.rs @@ -5,7 +5,7 @@ use crate::blocktree::Blocktree; #[cfg(all(feature = "chacha", feature = "cuda"))] use crate::chacha_cuda::chacha_cbc_encrypt_file_many_keys; -use crate::client::mk_client_with_timeout; +use crate::cluster_client::mk_client_with_timeout; use crate::cluster_info::ClusterInfo; use crate::entry::{Entry, EntryReceiver}; use crate::result::{Error, Result}; diff --git a/core/src/thin_client.rs b/core/src/thin_client.rs deleted file mode 100644 index 715619ef1..000000000 --- a/core/src/thin_client.rs +++ /dev/null @@ -1,626 +0,0 @@ -//! 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. - -use crate::contact_info::ContactInfo; -use crate::fullnode::{Fullnode, FullnodeConfig}; -use crate::packet::PACKET_DATA_SIZE; -use crate::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; -use bincode::serialize_into; -use bs58; -use serde_json; -use solana_metrics; -use solana_metrics::influxdb; -use solana_sdk::account::Account; -use solana_sdk::hash::Hash; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; -use solana_sdk::system_transaction::SystemTransaction; -use solana_sdk::timing; -use solana_sdk::transaction::Transaction; -use std; -use std::io; -use std::net::{SocketAddr, UdpSocket}; -use std::sync::Arc; -use std::thread::sleep; -use std::time::Duration; -use std::time::Instant; - -/// An object for querying and sending transactions to the network. -pub struct ThinClient { - rpc_addr: SocketAddr, - transactions_addr: SocketAddr, - transactions_socket: UdpSocket, - rpc_client: RpcClient, -} - -impl ThinClient { - /// Create a new ThinClient that will interface with the Rpc at `rpc_addr` using TCP - /// and the Tpu at `transactions_addr` over `transactions_socket` using UDP. - pub fn new( - rpc_addr: SocketAddr, - transactions_addr: SocketAddr, - transactions_socket: UdpSocket, - ) -> Self { - Self::new_from_client( - rpc_addr, - transactions_addr, - transactions_socket, - RpcClient::new_from_socket(rpc_addr), - ) - } - - pub fn new_with_timeout( - rpc_addr: SocketAddr, - transactions_addr: SocketAddr, - transactions_socket: UdpSocket, - timeout: Duration, - ) -> Self { - let rpc_client = RpcClient::new_with_timeout(rpc_addr, timeout); - Self::new_from_client(rpc_addr, transactions_addr, transactions_socket, rpc_client) - } - - fn new_from_client( - rpc_addr: SocketAddr, - transactions_addr: SocketAddr, - transactions_socket: UdpSocket, - rpc_client: RpcClient, - ) -> Self { - ThinClient { - rpc_client, - rpc_addr, - transactions_addr, - transactions_socket, - } - } - - /// Send a signed Transaction to the server for processing. This method - /// does not wait for a response. - pub fn transfer_signed(&self, transaction: &Transaction) -> io::Result { - let mut buf = vec![0; transaction.serialized_size().unwrap() as usize]; - let mut wr = std::io::Cursor::new(&mut buf[..]); - serialize_into(&mut wr, &transaction) - .expect("serialize Transaction in pub fn transfer_signed"); - assert!(buf.len() < PACKET_DATA_SIZE); - self.transactions_socket - .send_to(&buf[..], &self.transactions_addr)?; - Ok(transaction.signatures[0]) - } - - /// Retry a sending a signed Transaction to the server for processing. - pub fn retry_transfer( - &mut self, - keypair: &Keypair, - transaction: &mut Transaction, - tries: usize, - ) -> io::Result { - for x in 0..tries { - transaction.sign(&[keypair], self.get_recent_blockhash()); - let mut buf = vec![0; transaction.serialized_size().unwrap() as usize]; - let mut wr = std::io::Cursor::new(&mut buf[..]); - serialize_into(&mut wr, &transaction) - .expect("serialize Transaction in pub fn transfer_signed"); - self.transactions_socket - .send_to(&buf[..], &self.transactions_addr)?; - if self.poll_for_signature(&transaction.signatures[0]).is_ok() { - return Ok(transaction.signatures[0]); - } - info!("{} tries failed transfer to {}", x, self.transactions_addr); - } - Err(io::Error::new( - io::ErrorKind::Other, - "retry_transfer failed", - )) - } - - /// Creates, signs, and processes a Transaction. Useful for writing unit-tests. - pub fn transfer( - &self, - lamports: u64, - keypair: &Keypair, - to: &Pubkey, - blockhash: &Hash, - ) -> io::Result { - debug!( - "transfer: lamports={} from={:?} to={:?} blockhash={:?}", - lamports, - keypair.pubkey(), - to, - blockhash - ); - let now = Instant::now(); - let transaction = SystemTransaction::new_account(keypair, to, lamports, *blockhash, 0); - let result = self.transfer_signed(&transaction); - solana_metrics::submit( - influxdb::Point::new("thinclient") - .add_tag("op", influxdb::Value::String("transfer".to_string())) - .add_field( - "duration_ms", - influxdb::Value::Integer(timing::duration_as_ms(&now.elapsed()) as i64), - ) - .to_owned(), - ); - result - } - - pub fn get_account_userdata(&mut self, pubkey: &Pubkey) -> io::Result>> { - let params = json!([format!("{}", pubkey)]); - let response = - self.rpc_client - .make_rpc_request(1, RpcRequest::GetAccountInfo, Some(params)); - match response { - Ok(account_json) => { - let account: Account = - serde_json::from_value(account_json).expect("deserialize account"); - Ok(Some(account.userdata)) - } - Err(error) => { - debug!("get_account_userdata failed: {:?}", error); - Err(io::Error::new( - io::ErrorKind::Other, - "get_account_userdata failed", - )) - } - } - } - - /// Request the balance of the user holding `pubkey`. This method blocks - /// until the server sends a response. If the response packet is dropped - /// by the network, this method will hang indefinitely. - pub fn get_balance(&mut self, pubkey: &Pubkey) -> io::Result { - trace!("get_balance sending request to {}", self.rpc_addr); - let params = json!([format!("{}", pubkey)]); - let response = - self.rpc_client - .make_rpc_request(1, RpcRequest::GetAccountInfo, Some(params)); - - response - .and_then(|account_json| { - let account: Account = - serde_json::from_value(account_json).expect("deserialize account"); - trace!("Response account {:?} {:?}", pubkey, account); - trace!("get_balance {:?}", account.lamports); - Ok(account.lamports) - }) - .map_err(|error| { - debug!("Response account {}: None (error: {:?})", pubkey, error); - io::Error::new(io::ErrorKind::Other, "AccountNotFound") - }) - } - - /// Request the transaction count. If the response packet is dropped by the network, - /// this method will try again 5 times. - pub fn transaction_count(&mut self) -> u64 { - debug!("transaction_count"); - for _tries in 0..5 { - let response = - self.rpc_client - .make_rpc_request(1, RpcRequest::GetTransactionCount, None); - - match response { - Ok(value) => { - debug!("transaction_count response: {:?}", value); - let transaction_count = value.as_u64().unwrap(); - return transaction_count; - } - Err(error) => { - debug!("transaction_count failed: {:?}", error); - } - }; - } - 0 - } - - /// Request the last Entry ID from the server without blocking. - /// Returns the blockhash Hash or None if there was no response from the server. - pub fn try_get_recent_blockhash(&mut self, mut num_retries: u64) -> Option { - loop { - trace!("try_get_recent_blockhash send_to {}", &self.rpc_addr); - let response = - self.rpc_client - .make_rpc_request(1, RpcRequest::GetRecentBlockhash, None); - - match response { - Ok(value) => { - let blockhash_str = value.as_str().unwrap(); - let blockhash_vec = bs58::decode(blockhash_str).into_vec().unwrap(); - return Some(Hash::new(&blockhash_vec)); - } - Err(error) => { - debug!("thin_client get_recent_blockhash error: {:?}", error); - num_retries -= 1; - if num_retries == 0 { - return None; - } - } - } - } - } - - /// Request the last Entry ID from the server. This method blocks - /// until the server sends a response. - pub fn get_recent_blockhash(&mut self) -> Hash { - loop { - trace!("get_recent_blockhash send_to {}", &self.rpc_addr); - if let Some(hash) = self.try_get_recent_blockhash(10) { - return hash; - } - } - } - - /// Request a new last Entry ID from the server. This method blocks - /// until the server sends a response. - pub fn get_next_blockhash(&mut self, previous_blockhash: &Hash) -> Hash { - self.get_next_blockhash_ext(previous_blockhash, &|| { - sleep(Duration::from_millis(100)); - }) - } - pub fn get_next_blockhash_ext(&mut self, previous_blockhash: &Hash, func: &Fn()) -> Hash { - loop { - let blockhash = self.get_recent_blockhash(); - if blockhash != *previous_blockhash { - break blockhash; - } - debug!("Got same blockhash ({:?}), will retry...", blockhash); - func() - } - } - - pub fn submit_poll_balance_metrics(elapsed: &Duration) { - solana_metrics::submit( - influxdb::Point::new("thinclient") - .add_tag("op", influxdb::Value::String("get_balance".to_string())) - .add_field( - "duration_ms", - influxdb::Value::Integer(timing::duration_as_ms(elapsed) as i64), - ) - .to_owned(), - ); - } - - pub fn poll_balance_with_timeout( - &mut self, - pubkey: &Pubkey, - polling_frequency: &Duration, - timeout: &Duration, - ) -> io::Result { - let now = Instant::now(); - loop { - match self.get_balance(&pubkey) { - Ok(bal) => { - ThinClient::submit_poll_balance_metrics(&now.elapsed()); - return Ok(bal); - } - Err(e) => { - sleep(*polling_frequency); - if now.elapsed() > *timeout { - ThinClient::submit_poll_balance_metrics(&now.elapsed()); - return Err(e); - } - } - }; - } - } - - pub fn poll_get_balance(&mut self, pubkey: &Pubkey) -> io::Result { - self.poll_balance_with_timeout(pubkey, &Duration::from_millis(100), &Duration::from_secs(1)) - } - - /// Poll the server to confirm a transaction. - pub fn poll_for_signature(&mut self, signature: &Signature) -> io::Result<()> { - let now = Instant::now(); - while !self.check_signature(signature) { - if now.elapsed().as_secs() > 15 { - // TODO: Return a better error. - return Err(io::Error::new(io::ErrorKind::Other, "signature not found")); - } - sleep(Duration::from_millis(250)); - } - Ok(()) - } - - /// Check a signature in the bank. This method blocks - /// until the server sends a response. - pub fn check_signature(&mut self, signature: &Signature) -> bool { - trace!("check_signature: {:?}", signature); - let params = json!([format!("{}", signature)]); - let now = Instant::now(); - - loop { - let response = self.rpc_client.make_rpc_request( - 1, - RpcRequest::ConfirmTransaction, - Some(params.clone()), - ); - - match response { - Ok(confirmation) => { - let signature_status = confirmation.as_bool().unwrap(); - if signature_status { - trace!("Response found signature"); - } else { - trace!("Response signature not found"); - } - solana_metrics::submit( - influxdb::Point::new("thinclient") - .add_tag("op", influxdb::Value::String("check_signature".to_string())) - .add_field( - "duration_ms", - influxdb::Value::Integer( - timing::duration_as_ms(&now.elapsed()) as i64 - ), - ) - .to_owned(), - ); - return signature_status; - } - Err(err) => { - debug!("check_signature request failed: {:?}", err); - } - }; - } - } - pub fn fullnode_exit(&mut self) -> io::Result { - trace!("fullnode_exit sending request to {}", self.rpc_addr); - let response = self - .rpc_client - .make_rpc_request(1, RpcRequest::FullnodeExit, None) - .map_err(|error| { - debug!("Response from {} fullndoe_exit: {}", self.rpc_addr, error); - io::Error::new(io::ErrorKind::Other, "FullodeExit request failure") - })?; - serde_json::from_value(response).map_err(|error| { - debug!( - "ParseError: from {} fullndoe_exit: {}", - self.rpc_addr, error - ); - io::Error::new(io::ErrorKind::Other, "FullodeExit parse failure") - }) - } -} - -impl Drop for ThinClient { - fn drop(&mut self) { - solana_metrics::flush(); - } -} - -pub fn retry_get_balance( - client: &mut ThinClient, - bob_pubkey: &Pubkey, - expected_balance: Option, -) -> Option { - const LAST: usize = 30; - for run in 0..LAST { - let balance_result = client.poll_get_balance(bob_pubkey); - if expected_balance.is_none() { - return balance_result.ok(); - } - trace!( - "retry_get_balance[{}] {:?} {:?}", - run, - balance_result, - expected_balance - ); - if let (Some(expected_balance), Ok(balance_result)) = (expected_balance, balance_result) { - if expected_balance == balance_result { - return Some(balance_result); - } - } - } - None -} - -pub fn new_fullnode() -> (Fullnode, ContactInfo, Keypair, String) { - use crate::blocktree::create_new_tmp_ledger; - use crate::cluster_info::Node; - use crate::fullnode::Fullnode; - use solana_sdk::genesis_block::GenesisBlock; - use solana_sdk::signature::KeypairUtil; - - let node_keypair = Arc::new(Keypair::new()); - let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey()); - let contact_info = node.info.clone(); - - let (mut genesis_block, mint_keypair) = - GenesisBlock::new_with_leader(10_000, &contact_info.id, 42); - genesis_block - .native_programs - .push(("solana_budget_program".to_string(), solana_budget_api::id())); - - let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block); - - let voting_keypair = Keypair::new(); - let node = Fullnode::new( - node, - &node_keypair, - &ledger_path, - &voting_keypair.pubkey(), - voting_keypair, - None, - &FullnodeConfig::default(), - ); - - (node, contact_info, mint_keypair, ledger_path) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::client::mk_client; - use crate::gossip_service::discover; - use bincode::{deserialize, serialize}; - use solana_sdk::system_instruction::SystemInstruction; - use solana_vote_api::vote_state::VoteState; - use solana_vote_api::vote_transaction::VoteTransaction; - use std::fs::remove_dir_all; - - #[test] - fn test_thin_client_basic() { - solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_fullnode(); - let bob_pubkey = Keypair::new().pubkey(); - discover(&leader_data.gossip, 1).unwrap(); - - let mut client = mk_client(&leader_data); - - let transaction_count = client.transaction_count(); - assert_eq!(transaction_count, 0); - - let blockhash = client.get_recent_blockhash(); - info!("test_thin_client blockhash: {:?}", blockhash); - - let signature = client - .transfer(500, &alice, &bob_pubkey, &blockhash) - .unwrap(); - info!("test_thin_client signature: {:?}", signature); - client.poll_for_signature(&signature).unwrap(); - - let balance = client.get_balance(&bob_pubkey); - assert_eq!(balance.unwrap(), 500); - - let transaction_count = client.transaction_count(); - assert_eq!(transaction_count, 1); - server.close().unwrap(); - remove_dir_all(ledger_path).unwrap(); - } - - #[test] - #[ignore] - fn test_bad_sig() { - solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_fullnode(); - let bob_pubkey = Keypair::new().pubkey(); - discover(&leader_data.gossip, 1).unwrap(); - - let mut client = mk_client(&leader_data); - - let blockhash = client.get_recent_blockhash(); - - let tx = SystemTransaction::new_account(&alice, &bob_pubkey, 500, blockhash, 0); - - let _sig = client.transfer_signed(&tx).unwrap(); - - let blockhash = client.get_recent_blockhash(); - - let mut tr2 = SystemTransaction::new_account(&alice, &bob_pubkey, 501, blockhash, 0); - let mut instruction2 = deserialize(tr2.userdata(0)).unwrap(); - if let SystemInstruction::Move { ref mut lamports } = instruction2 { - *lamports = 502; - } - tr2.instructions[0].userdata = serialize(&instruction2).unwrap(); - let signature = client.transfer_signed(&tr2).unwrap(); - client.poll_for_signature(&signature).unwrap(); - - let balance = client.get_balance(&bob_pubkey); - assert_eq!(balance.unwrap(), 1001); - server.close().unwrap(); - remove_dir_all(ledger_path).unwrap(); - } - - #[test] - fn test_register_vote_account() { - solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_fullnode(); - discover(&leader_data.gossip, 1).unwrap(); - - let mut client = mk_client(&leader_data); - - // Create the validator account, transfer some lamports to that account - let validator_keypair = Keypair::new(); - let blockhash = client.get_recent_blockhash(); - let signature = client - .transfer(500, &alice, &validator_keypair.pubkey(), &blockhash) - .unwrap(); - - client.poll_for_signature(&signature).unwrap(); - - // Create and register the vote account - let validator_vote_account_keypair = Keypair::new(); - let vote_account_id = validator_vote_account_keypair.pubkey(); - let blockhash = client.get_recent_blockhash(); - - let transaction = - VoteTransaction::new_account(&validator_keypair, &vote_account_id, blockhash, 1, 1); - let signature = client.transfer_signed(&transaction).unwrap(); - client.poll_for_signature(&signature).unwrap(); - - let balance = retry_get_balance(&mut client, &vote_account_id, Some(1)) - .expect("Expected balance for new account to exist"); - assert_eq!(balance, 1); - - const LAST: usize = 30; - for run in 0..=LAST { - let account_user_data = client - .get_account_userdata(&vote_account_id) - .expect("Expected valid response for account userdata") - .expect("Expected valid account userdata to exist after account creation"); - - let vote_state = VoteState::deserialize(&account_user_data); - - if vote_state.map(|vote_state| vote_state.delegate_id) == Ok(vote_account_id) { - break; - } - - if run == LAST { - panic!("Expected successful vote account registration"); - } - sleep(Duration::from_millis(900)); - } - - server.close().unwrap(); - remove_dir_all(ledger_path).unwrap(); - } - - #[test] - fn test_transaction_count() { - // set a bogus address, see that we don't hang - solana_logger::setup(); - let addr = "0.0.0.0:1234".parse().unwrap(); - let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); - let mut client = - ThinClient::new_with_timeout(addr, addr, transactions_socket, Duration::from_secs(2)); - assert_eq!(client.transaction_count(), 0); - } - - #[test] - fn test_zero_balance_after_nonzero() { - solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_fullnode(); - let bob_keypair = Keypair::new(); - discover(&leader_data.gossip, 1).unwrap(); - - let mut client = mk_client(&leader_data); - let blockhash = client.get_recent_blockhash(); - info!("test_thin_client blockhash: {:?}", blockhash); - - let starting_alice_balance = client.poll_get_balance(&alice.pubkey()).unwrap(); - info!("Alice has {} lamports", starting_alice_balance); - - info!("Give Bob 500 lamports"); - let signature = client - .transfer(500, &alice, &bob_keypair.pubkey(), &blockhash) - .unwrap(); - client.poll_for_signature(&signature).unwrap(); - - let bob_balance = client.poll_get_balance(&bob_keypair.pubkey()); - assert_eq!(bob_balance.unwrap(), 500); - - info!("Take Bob's 500 lamports away"); - let signature = client - .transfer(500, &bob_keypair, &alice.pubkey(), &blockhash) - .unwrap(); - client.poll_for_signature(&signature).unwrap(); - let alice_balance = client.poll_get_balance(&alice.pubkey()).unwrap(); - assert_eq!(alice_balance, starting_alice_balance); - - info!("Should get an error when Bob's balance hits zero and is purged"); - let bob_balance = client.poll_get_balance(&bob_keypair.pubkey()); - info!("Bob's balance is {:?}", bob_balance); - assert!(bob_balance.is_err(),); - - server.close().unwrap(); - remove_dir_all(ledger_path).unwrap(); - } -} diff --git a/core/src/voting_keypair.rs b/core/src/voting_keypair.rs index 95ee51da2..24f5e9937 100644 --- a/core/src/voting_keypair.rs +++ b/core/src/voting_keypair.rs @@ -1,7 +1,7 @@ //! The `vote_signer_proxy` votes on the `blockhash` of the bank at a regular cadence -use crate::rpc_request::{RpcClient, RpcRequest}; use jsonrpc_core; +use solana_client::rpc_request::{RpcClient, RpcRequest}; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; use solana_vote_signer::rpc::LocalVoteSigner; diff --git a/tests/replicator.rs b/tests/replicator.rs index d9446e603..448fc6701 100644 --- a/tests/replicator.rs +++ b/tests/replicator.rs @@ -12,7 +12,7 @@ use bincode::deserialize; use solana::blocktree::{ create_new_tmp_ledger, get_tmp_ledger_path, tmp_copy_blocktree, Blocktree, }; -use solana::client::mk_client; +use solana::cluster_client::mk_client; use solana::cluster_info::{ClusterInfo, Node}; use solana::contact_info::ContactInfo; use solana::entry::Entry; @@ -190,7 +190,7 @@ fn test_replicator_startup_basic() { // chacha is not enabled #[cfg(feature = "chacha")] { - use solana::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; + use solana_client::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; use std::thread::sleep; info!( diff --git a/tests/rpc.rs b/tests/rpc.rs index ac798ceb9..588a68dec 100644 --- a/tests/rpc.rs +++ b/tests/rpc.rs @@ -3,8 +3,8 @@ use log::*; use reqwest; use reqwest::header::CONTENT_TYPE; use serde_json::{json, Value}; -use solana::rpc_request::get_rpc_request_str; -use solana::thin_client::new_fullnode; +use solana::fullnode::new_fullnode_for_tests; +use solana_client::rpc_request::get_rpc_request_str; use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; @@ -16,7 +16,7 @@ use std::time::Duration; fn test_rpc_send_tx() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let bob_pubkey = Keypair::new().pubkey(); let client = reqwest::Client::new(); diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index ff13928fe..e3a85044c 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -18,6 +18,7 @@ log = "0.4.2" serde_json = "1.0.39" solana = { path = "../core", version = "0.13.0" } solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" } +solana-client = { path = "../client", version = "0.13.0" } solana-drone = { path = "../drone", version = "0.13.0" } solana-logger = { path = "../logger", version = "0.13.0" } solana-sdk = { path = "../sdk", version = "0.13.0" } diff --git a/wallet/src/wallet.rs b/wallet/src/wallet.rs index 9c006c32b..02166bb6c 100644 --- a/wallet/src/wallet.rs +++ b/wallet/src/wallet.rs @@ -5,15 +5,15 @@ use clap::ArgMatches; use log::*; use serde_json; use serde_json::json; -#[cfg(test)] -use solana::rpc_mock::{request_airdrop_transaction, MockRpcClient as RpcClient}; -#[cfg(not(test))] -use solana::rpc_request::RpcClient; -use solana::rpc_request::{get_rpc_request_str, RpcRequest}; use solana::rpc_service::RPC_PORT; use solana::rpc_status::RpcSignatureStatus; use solana_budget_api; use solana_budget_api::budget_transaction::BudgetTransaction; +#[cfg(test)] +use solana_client::rpc_mock::{request_airdrop_transaction, MockRpcClient as RpcClient}; +#[cfg(not(test))] +use solana_client::rpc_request::RpcClient; +use solana_client::rpc_request::{get_rpc_request_str, RpcRequest}; #[cfg(not(test))] use solana_drone::drone::request_airdrop_transaction; use solana_drone::drone::DRONE_PORT; @@ -996,8 +996,8 @@ mod tests { use super::*; use clap::{App, Arg, ArgGroup, SubCommand}; use serde_json::Value; - use solana::rpc_mock::{PUBKEY, SIGNATURE}; use solana::socketaddr; + use solana_client::rpc_mock::{PUBKEY, SIGNATURE}; use solana_sdk::signature::{gen_keypair_file, read_keypair, read_pkcs8, Keypair, KeypairUtil}; use std::fs; use std::net::{Ipv4Addr, SocketAddr}; diff --git a/wallet/tests/deploy.rs b/wallet/tests/deploy.rs index 91bfa3f33..a9eea663c 100644 --- a/wallet/tests/deploy.rs +++ b/wallet/tests/deploy.rs @@ -1,6 +1,6 @@ use serde_json::{json, Value}; -use solana::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; -use solana::thin_client::new_fullnode; +use solana::fullnode::new_fullnode_for_tests; +use solana_client::rpc_request::{RpcClient, RpcRequest, RpcRequestHandler}; use solana_drone::drone::run_local_drone; use solana_sdk::bpf_loader; use solana_wallet::wallet::{process_command, WalletCommand, WalletConfig}; @@ -19,7 +19,7 @@ fn test_wallet_deploy_program() { pathbuf.push("noop"); pathbuf.set_extension("so"); - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let (sender, receiver) = channel(); run_local_drone(alice, sender); diff --git a/wallet/tests/pay.rs b/wallet/tests/pay.rs index 1f72fb1d2..0dd950e38 100644 --- a/wallet/tests/pay.rs +++ b/wallet/tests/pay.rs @@ -1,6 +1,6 @@ use chrono::prelude::*; use serde_json::Value; -use solana::rpc_request::RpcClient; +use solana_client::rpc_request::RpcClient; use solana_drone::drone::run_local_drone; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; @@ -11,7 +11,7 @@ use std::fs::remove_dir_all; use std::sync::mpsc::channel; #[cfg(test)] -use solana::thin_client::new_fullnode; +use solana::fullnode::new_fullnode_for_tests; fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { let balance = client.retry_get_balance(1, pubkey, 1).unwrap().unwrap(); @@ -20,7 +20,7 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { #[test] fn test_wallet_timestamp_tx() { - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let bob_pubkey = Keypair::new().pubkey(); let (sender, receiver) = channel(); @@ -80,7 +80,7 @@ fn test_wallet_timestamp_tx() { #[test] fn test_wallet_witness_tx() { - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let bob_pubkey = Keypair::new().pubkey(); let (sender, receiver) = channel(); @@ -137,7 +137,7 @@ fn test_wallet_witness_tx() { #[test] fn test_wallet_cancel_tx() { - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let bob_pubkey = Keypair::new().pubkey(); let (sender, receiver) = channel(); diff --git a/wallet/tests/request_airdrop.rs b/wallet/tests/request_airdrop.rs index 2c3153a5f..5d723b09f 100644 --- a/wallet/tests/request_airdrop.rs +++ b/wallet/tests/request_airdrop.rs @@ -1,5 +1,5 @@ -use solana::rpc_request::RpcClient; -use solana::thin_client::new_fullnode; +use solana::fullnode::new_fullnode_for_tests; +use solana_client::rpc_request::RpcClient; use solana_drone::drone::run_local_drone; use solana_sdk::signature::KeypairUtil; use solana_wallet::wallet::{process_command, WalletCommand, WalletConfig}; @@ -8,7 +8,7 @@ use std::sync::mpsc::channel; #[test] fn test_wallet_request_airdrop() { - let (server, leader_data, alice, ledger_path) = new_fullnode(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); let (sender, receiver) = channel(); run_local_drone(alice, sender); let drone_addr = receiver.recv().unwrap();