Cleanly handle RPC servers that don't have --enable-rpc-transaction-history enabled

This commit is contained in:
Michael Vines
2020-10-12 18:06:10 -07:00
parent 247228ee61
commit 14d793b22c
3 changed files with 44 additions and 18 deletions

View File

@ -23,8 +23,12 @@ use solana_cli_output::{
CliStakeType, CliStakeType,
}; };
use solana_client::{ use solana_client::{
blockhash_query::BlockhashQuery, nonce_utils, rpc_client::RpcClient, blockhash_query::BlockhashQuery,
rpc_request::DELINQUENT_VALIDATOR_SLOT_DISTANCE, client_error::{ClientError, ClientErrorKind},
nonce_utils,
rpc_client::RpcClient,
rpc_custom_error,
rpc_request::{self, DELINQUENT_VALIDATOR_SLOT_DISTANCE},
}; };
use solana_remote_wallet::remote_wallet::RemoteWalletManager; use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{ use solana_sdk::{
@ -1605,10 +1609,26 @@ pub(crate) fn fetch_epoch_rewards(
.get(0) .get(0)
.ok_or_else(|| format!("Unable to fetch first confirmed block for epoch {}", epoch))?; .ok_or_else(|| format!("Unable to fetch first confirmed block for epoch {}", epoch))?;
let first_confirmed_block = rpc_client.get_confirmed_block_with_encoding( let first_confirmed_block = match rpc_client.get_confirmed_block_with_encoding(
first_confirmed_block_in_epoch, first_confirmed_block_in_epoch,
solana_transaction_status::UiTransactionEncoding::Base64, solana_transaction_status::UiTransactionEncoding::Base64,
)?; ) {
Ok(first_confirmed_block) => first_confirmed_block,
Err(ClientError {
kind:
ClientErrorKind::RpcError(rpc_request::RpcError::RpcResponseError {
code: rpc_custom_error::JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
message: _,
}),
request: _,
}) => {
// RPC node doesn't have this block
break;
}
Err(err) => {
return Err(err.into());
}
};
let epoch_start_time = if let Some(block_time) = first_confirmed_block.block_time { let epoch_start_time = if let Some(block_time) = first_confirmed_block.block_time {
block_time block_time

View File

@ -50,10 +50,10 @@ impl Into<TransportError> for ClientErrorKind {
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("{kind}")] #[error("{kind}")]
pub struct ClientError { pub struct ClientError {
request: Option<rpc_request::RpcRequest>, pub request: Option<rpc_request::RpcRequest>,
#[source] #[source]
kind: ClientErrorKind, pub kind: ClientErrorKind,
} }
impl ClientError { impl ClientError {

View File

@ -4,12 +4,12 @@ use crate::rpc_response::RpcSimulateTransactionResult;
use jsonrpc_core::{Error, ErrorCode}; use jsonrpc_core::{Error, ErrorCode};
use solana_sdk::clock::Slot; use solana_sdk::clock::Slot;
const JSON_RPC_SERVER_ERROR_1: i64 = -32001; pub const JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: i64 = -32001;
const JSON_RPC_SERVER_ERROR_2: i64 = -32002; pub const JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE: i64 = -32002;
const JSON_RPC_SERVER_ERROR_3: i64 = -32003; pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE: i64 = -32003;
const JSON_RPC_SERVER_ERROR_4: i64 = -32004; pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004;
const JSON_RPC_SERVER_ERROR_5: i64 = -32005; pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005;
const JSON_RPC_SERVER_ERROR_6: i64 = -32006; pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
pub enum RpcCustomError { pub enum RpcCustomError {
BlockCleanedUp { BlockCleanedUp {
@ -35,7 +35,7 @@ impl From<RpcCustomError> for Error {
slot, slot,
first_available_block, first_available_block,
} => Self { } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_1), code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP),
message: format!( message: format!(
"Block {} cleaned up, does not exist on node. First available block: {}", "Block {} cleaned up, does not exist on node. First available block: {}",
slot, first_available_block, slot, first_available_block,
@ -43,27 +43,33 @@ impl From<RpcCustomError> for Error {
data: None, data: None,
}, },
RpcCustomError::SendTransactionPreflightFailure { message, result } => Self { RpcCustomError::SendTransactionPreflightFailure { message, result } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_2), code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
),
message, message,
data: Some(serde_json::json!(result)), data: Some(serde_json::json!(result)),
}, },
RpcCustomError::TransactionSignatureVerificationFailure => Self { RpcCustomError::TransactionSignatureVerificationFailure => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_3), code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
),
message: "Transaction signature verification failure".to_string(), message: "Transaction signature verification failure".to_string(),
data: None, data: None,
}, },
RpcCustomError::BlockNotAvailable { slot } => Self { RpcCustomError::BlockNotAvailable { slot } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_4), code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE),
message: format!("Block not available for slot {}", slot), message: format!("Block not available for slot {}", slot),
data: None, data: None,
}, },
RpcCustomError::RpcNodeUnhealthy => Self { RpcCustomError::RpcNodeUnhealthy => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_5), code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY),
message: "RPC node is unhealthy".to_string(), message: "RPC node is unhealthy".to_string(),
data: None, data: None,
}, },
RpcCustomError::TransactionPrecompileVerificationFailure(e) => Self { RpcCustomError::TransactionPrecompileVerificationFailure(e) => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_6), code: ErrorCode::ServerError(
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
),
message: format!("Transaction precompile verification failure {:?}", e), message: format!("Transaction precompile verification failure {:?}", e),
data: None, data: None,
}, },