Use rooted bank by default in rpc bank selection (#6759)

* Name anonymous parameters for clarity

* Add CommitmentConfig to select bank for rpc

* Add commitment information to jsonrpc docs

* Update send_and_confirm retries as per commitment defaults

* Pass CommitmentConfig into client requests; also various 'use' cleanup

* Use _with_commitment methods to speed local_cluster tests

* Pass CommitmentConfig into Archiver in order to enable quick confirmations in local_cluster tests

* Restore solana ping speed

* Increase wallet-sanity timeout to account for longer confirmation time
This commit is contained in:
Tyera Eulberg
2019-11-06 14:15:00 -07:00
committed by GitHub
parent 5e8668799c
commit b3a75a60a4
27 changed files with 1225 additions and 463 deletions

View File

@@ -1,14 +1,17 @@
use crate::client_error::ClientError;
use crate::generic_rpc_client_request::GenericRpcClientRequest;
use crate::mock_rpc_client_request::MockRpcClientRequest;
use crate::rpc_client_request::RpcClientRequest;
use crate::rpc_request::{RpcEpochInfo, RpcRequest, RpcVoteAccountStatus};
use crate::{
client_error::ClientError,
generic_rpc_client_request::GenericRpcClientRequest,
mock_rpc_client_request::MockRpcClientRequest,
rpc_client_request::RpcClientRequest,
rpc_request::{RpcEpochInfo, RpcRequest, RpcVoteAccountStatus},
};
use bincode::serialize;
use log::*;
use serde_json::{json, Value};
use solana_sdk::{
account::Account,
clock::{Slot, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
commitment_config::CommitmentConfig,
epoch_schedule::EpochSchedule,
fee_calculator::FeeCalculator,
hash::Hash,
@@ -54,10 +57,10 @@ impl RpcClient {
pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
let serialized = serialize(transaction).unwrap();
let params = json!([serialized]);
let params = json!(serialized);
let signature = self
.client
.send(&RpcRequest::SendTransaction, Some(params), 5)?;
.send(&RpcRequest::SendTransaction, Some(params), 5, None)?;
if signature.as_str().is_none() {
Err(io::Error::new(
io::ErrorKind::Other,
@@ -73,19 +76,37 @@ impl RpcClient {
&self,
signature: &str,
) -> Result<Option<transaction::Result<()>>, ClientError> {
let params = json!([signature.to_string()]);
let signature_status =
self.client
.send(&RpcRequest::GetSignatureStatus, Some(params), 5)?;
self.get_signature_status_with_commitment(signature, CommitmentConfig::default())
}
pub fn get_signature_status_with_commitment(
&self,
signature: &str,
commitment_config: CommitmentConfig,
) -> Result<Option<transaction::Result<()>>, ClientError> {
let params = json!(signature.to_string());
let signature_status = self.client.send(
&RpcRequest::GetSignatureStatus,
Some(params),
5,
commitment_config.ok(),
)?;
let result: Option<transaction::Result<()>> =
serde_json::from_value(signature_status).unwrap();
Ok(result)
}
pub fn get_slot(&self) -> io::Result<Slot> {
self.get_slot_with_commitment(CommitmentConfig::default())
}
pub fn get_slot_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> io::Result<Slot> {
let response = self
.client
.send(&RpcRequest::GetSlot, None, 0)
.send(&RpcRequest::GetSlot, None, 0, commitment_config.ok())
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -104,7 +125,7 @@ impl RpcClient {
pub fn get_vote_accounts(&self) -> io::Result<RpcVoteAccountStatus> {
let response = self
.client
.send(&RpcRequest::GetVoteAccounts, None, 0)
.send(&RpcRequest::GetVoteAccounts, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -123,7 +144,7 @@ impl RpcClient {
pub fn get_epoch_info(&self) -> io::Result<RpcEpochInfo> {
let response = self
.client
.send(&RpcRequest::GetEpochInfo, None, 0)
.send(&RpcRequest::GetEpochInfo, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -142,7 +163,7 @@ impl RpcClient {
pub fn get_epoch_schedule(&self) -> io::Result<EpochSchedule> {
let response = self
.client
.send(&RpcRequest::GetEpochSchedule, None, 0)
.send(&RpcRequest::GetEpochSchedule, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -161,7 +182,7 @@ impl RpcClient {
pub fn get_inflation(&self) -> io::Result<Inflation> {
let response = self
.client
.send(&RpcRequest::GetInflation, None, 0)
.send(&RpcRequest::GetInflation, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -180,7 +201,7 @@ impl RpcClient {
pub fn get_version(&self) -> io::Result<String> {
let response = self
.client
.send(&RpcRequest::GetVersion, None, 0)
.send(&RpcRequest::GetVersion, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -203,7 +224,7 @@ impl RpcClient {
) -> Result<String, ClientError> {
let mut send_retries = 20;
loop {
let mut status_retries = 4;
let mut status_retries = 15;
let signature_str = self.send_transaction(transaction)?;
let status = loop {
let status = self.get_signature_status(&signature_str)?;
@@ -216,10 +237,8 @@ impl RpcClient {
break status;
}
if cfg!(not(test)) {
// Retry ~twice during a slot
sleep(Duration::from_millis(
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
));
// Retry twice a second
sleep(Duration::from_millis(500));
}
};
send_retries = if let Some(result) = status.clone() {
@@ -252,7 +271,7 @@ impl RpcClient {
) -> Result<(), Box<dyn error::Error>> {
let mut send_retries = 5;
loop {
let mut status_retries = 4;
let mut status_retries = 15;
// Send all transactions
let mut transactions_signatures = vec![];
@@ -273,10 +292,8 @@ impl RpcClient {
status_retries -= 1;
if cfg!(not(test)) {
// Retry ~twice during a slot
sleep(Duration::from_millis(
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
));
// Retry twice a second
sleep(Duration::from_millis(500));
}
transactions_signatures = transactions_signatures
@@ -333,19 +350,30 @@ impl RpcClient {
pubkey: &Pubkey,
retries: usize,
) -> Result<Option<u64>, Box<dyn error::Error>> {
let params = json!([format!("{}", pubkey)]);
let params = json!(format!("{}", pubkey));
let res = self
.client
.send(&RpcRequest::GetBalance, Some(params), retries)?
.send(&RpcRequest::GetBalance, Some(params), retries, None)?
.as_u64();
Ok(res)
}
pub fn get_account(&self, pubkey: &Pubkey) -> io::Result<Account> {
let params = json!([format!("{}", pubkey)]);
let response = self
.client
.send(&RpcRequest::GetAccountInfo, Some(params), 0);
self.get_account_with_commitment(pubkey, CommitmentConfig::default())
}
pub fn get_account_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> io::Result<Account> {
let params = json!(format!("{}", pubkey));
let response = self.client.send(
&RpcRequest::GetAccountInfo,
Some(params),
0,
commitment_config.ok(),
);
response
.and_then(|account_json| {
@@ -366,13 +394,14 @@ impl RpcClient {
}
pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> io::Result<u64> {
let params = json!([data_len]);
let params = json!(data_len);
let minimum_balance_json = self
.client
.send(
&RpcRequest::GetMinimumBalanceForRentExemption,
Some(params),
0,
None,
)
.map_err(|err| {
io::Error::new(
@@ -398,18 +427,25 @@ impl RpcClient {
Ok(minimum_balance)
}
/// 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.
/// Request the balance of the account `pubkey`.
pub fn get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
self.get_account(pubkey).map(|account| account.lamports)
self.get_balance_with_commitment(pubkey, CommitmentConfig::default())
}
pub fn get_balance_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> io::Result<u64> {
self.get_account_with_commitment(pubkey, commitment_config)
.map(|account| account.lamports)
}
pub fn get_program_accounts(&self, pubkey: &Pubkey) -> io::Result<Vec<(Pubkey, Account)>> {
let params = json!([format!("{}", pubkey)]);
let params = json!(format!("{}", pubkey));
let response = self
.client
.send(&RpcRequest::GetProgramAccounts, Some(params), 0)
.send(&RpcRequest::GetProgramAccounts, Some(params), 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -438,12 +474,23 @@ impl RpcClient {
Ok(pubkey_accounts)
}
/// Request the transaction count. If the response packet is dropped by the network,
/// this method will try again 5 times.
/// Request the transaction count.
pub fn get_transaction_count(&self) -> io::Result<u64> {
self.get_transaction_count_with_commitment(CommitmentConfig::default())
}
pub fn get_transaction_count_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> io::Result<u64> {
let response = self
.client
.send(&RpcRequest::GetTransactionCount, None, 0)
.send(
&RpcRequest::GetTransactionCount,
None,
0,
commitment_config.ok(),
)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -460,9 +507,21 @@ impl RpcClient {
}
pub fn get_recent_blockhash(&self) -> io::Result<(Hash, FeeCalculator)> {
self.get_recent_blockhash_with_commitment(CommitmentConfig::default())
}
pub fn get_recent_blockhash_with_commitment(
&self,
commitment_config: CommitmentConfig,
) -> io::Result<(Hash, FeeCalculator)> {
let response = self
.client
.send(&RpcRequest::GetRecentBlockhash, None, 0)
.send(
&RpcRequest::GetRecentBlockhash,
None,
0,
commitment_config.ok(),
)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -518,7 +577,7 @@ impl RpcClient {
pub fn get_genesis_blockhash(&self) -> io::Result<Hash> {
let response = self
.client
.send(&RpcRequest::GetGenesisBlockhash, None, 0)
.send(&RpcRequest::GetGenesisBlockhash, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -542,15 +601,16 @@ impl RpcClient {
Ok(blockhash)
}
pub fn poll_balance_with_timeout(
pub fn poll_balance_with_timeout_and_commitment(
&self,
pubkey: &Pubkey,
polling_frequency: &Duration,
timeout: &Duration,
commitment_config: CommitmentConfig,
) -> io::Result<u64> {
let now = Instant::now();
loop {
match self.get_balance(&pubkey) {
match self.get_balance_with_commitment(&pubkey, commitment_config.clone()) {
Ok(bal) => {
return Ok(bal);
}
@@ -564,14 +624,29 @@ impl RpcClient {
}
}
pub fn poll_get_balance(&self, pubkey: &Pubkey) -> io::Result<u64> {
self.poll_balance_with_timeout(pubkey, &Duration::from_millis(100), &Duration::from_secs(1))
pub fn poll_get_balance_with_commitment(
&self,
pubkey: &Pubkey,
commitment_config: CommitmentConfig,
) -> io::Result<u64> {
self.poll_balance_with_timeout_and_commitment(
pubkey,
&Duration::from_millis(100),
&Duration::from_secs(1),
commitment_config,
)
}
pub fn wait_for_balance(&self, pubkey: &Pubkey, expected_balance: Option<u64>) -> Option<u64> {
pub fn wait_for_balance_with_commitment(
&self,
pubkey: &Pubkey,
expected_balance: Option<u64>,
commitment_config: CommitmentConfig,
) -> Option<u64> {
const LAST: usize = 30;
for run in 0..LAST {
let balance_result = self.poll_get_balance(pubkey);
let balance_result =
self.poll_get_balance_with_commitment(pubkey, commitment_config.clone());
if expected_balance.is_none() {
return balance_result.ok();
}
@@ -593,8 +668,23 @@ impl RpcClient {
/// Poll the server to confirm a transaction.
pub fn poll_for_signature(&self, signature: &Signature) -> io::Result<()> {
self.poll_for_signature_with_commitment(signature, CommitmentConfig::default())
}
/// Poll the server to confirm a transaction.
pub fn poll_for_signature_with_commitment(
&self,
signature: &Signature,
commitment_config: CommitmentConfig,
) -> io::Result<()> {
let now = Instant::now();
while !self.check_signature(signature) {
loop {
if let Ok(Some(_)) = self.get_signature_status_with_commitment(
&signature.to_string(),
commitment_config.clone(),
) {
break;
}
if now.elapsed().as_secs() > 15 {
// TODO: Return a better error.
return Err(io::Error::new(io::ErrorKind::Other, "signature not found"));
@@ -607,12 +697,15 @@ impl RpcClient {
/// Check a signature in the bank.
pub fn check_signature(&self, signature: &Signature) -> bool {
trace!("check_signature: {:?}", signature);
let params = json!([format!("{}", signature)]);
let params = json!(format!("{}", signature));
for _ in 0..30 {
let response =
self.client
.send(&RpcRequest::ConfirmTransaction, Some(params.clone()), 0);
let response = self.client.send(
&RpcRequest::ConfirmTransaction,
Some(params.clone()),
0,
Some(CommitmentConfig::recent()),
);
match response {
Ok(confirmation) => {
@@ -666,7 +759,7 @@ impl RpcClient {
debug!("check_confirmations request failed: {:?}", err);
}
};
if now.elapsed().as_secs() > 15 {
if now.elapsed().as_secs() > 20 {
info!(
"signature {} confirmed {} out of {} failed after {} ms",
signature,
@@ -690,13 +783,14 @@ impl RpcClient {
&self,
sig: &Signature,
) -> io::Result<usize> {
let params = json!([format!("{}", sig)]);
let params = json!(format!("{}", sig));
let response = self
.client
.send(
&RpcRequest::GetNumBlocksSinceSignatureConfirmation,
Some(params.clone()),
1,
CommitmentConfig::recent().ok(),
)
.map_err(|err| {
io::Error::new(
@@ -721,7 +815,7 @@ impl RpcClient {
pub fn validator_exit(&self) -> io::Result<bool> {
let response = self
.client
.send(&RpcRequest::ValidatorExit, None, 0)
.send(&RpcRequest::ValidatorExit, None, 0, None)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
@@ -742,8 +836,9 @@ impl RpcClient {
request: &RpcRequest,
params: Option<Value>,
retries: usize,
commitment: Option<CommitmentConfig>,
) -> Result<Value, ClientError> {
self.client.send(request, params, retries)
self.client.send(request, params, retries, commitment)
}
}
@@ -763,11 +858,12 @@ mod tests {
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
use serde_json::Number;
use solana_logger;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_transaction;
use solana_sdk::transaction::TransactionError;
use std::sync::mpsc::channel;
use std::thread;
use solana_sdk::{
signature::{Keypair, KeypairUtil},
system_transaction,
transaction::TransactionError,
};
use std::{sync::mpsc::channel, thread};
#[test]
fn test_make_rpc_request() {
@@ -808,10 +904,12 @@ mod tests {
&RpcRequest::GetBalance,
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"])),
0,
None,
);
assert_eq!(balance.unwrap().as_u64().unwrap(), 50);
let blockhash = rpc_client.retry_make_rpc_request(&RpcRequest::GetRecentBlockhash, None, 0);
let blockhash =
rpc_client.retry_make_rpc_request(&RpcRequest::GetRecentBlockhash, None, 0, None);
assert_eq!(
blockhash.unwrap().as_str().unwrap(),
"deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"
@@ -822,6 +920,7 @@ mod tests {
&RpcRequest::GetRecentBlockhash,
Some(json!("parameter")),
0,
None,
);
assert_eq!(blockhash.is_err(), true);
}
@@ -860,6 +959,7 @@ mod tests {
&RpcRequest::GetBalance,
Some(json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"])),
10,
None,
);
assert_eq!(balance.unwrap().as_u64().unwrap(), 5);
}