From 965204b8e0f48c2d566e9c35b4ca6e7b80a66630 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Mon, 11 May 2020 15:47:40 -0600 Subject: [PATCH] Check slot cleaned up for RPC blockstore/slot queries (#9982) automerge --- core/src/lib.rs | 1 + core/src/rpc.rs | 62 ++++++++++++++++++++++++++++--------------- core/src/rpc_error.rs | 45 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 core/src/rpc_error.rs diff --git a/core/src/lib.rs b/core/src/lib.rs index 01afae5f1b..1e1114ee3c 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -40,6 +40,7 @@ mod result; pub mod retransmit_stage; pub mod rewards_recorder_service; pub mod rpc; +pub mod rpc_error; pub mod rpc_pubsub; pub mod rpc_pubsub_service; pub mod rpc_service; diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 32a524c074..7e144fbb99 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -5,11 +5,12 @@ use crate::{ commitment::{BlockCommitmentArray, BlockCommitmentCache}, contact_info::ContactInfo, non_circulating_supply::calculate_non_circulating_supply, + rpc_error::RpcCustomError, storage_stage::StorageState, validator::ValidatorExit, }; use bincode::serialize; -use jsonrpc_core::{Error, ErrorCode, Metadata, Result}; +use jsonrpc_core::{Error, Metadata, Result}; use jsonrpc_derive::rpc; use solana_client::{ rpc_request::{ @@ -18,7 +19,9 @@ use solana_client::{ rpc_response::*, }; use solana_faucet::faucet::request_airdrop_transaction; -use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore}; +use solana_ledger::{ + bank_forks::BankForks, blockstore::Blockstore, blockstore_db::BlockstoreError, +}; use solana_perf::packet::PACKET_DATA_SIZE; use solana_runtime::{accounts::AccountAddressFilter, bank::Bank}; use solana_sdk::{ @@ -46,7 +49,6 @@ use std::{ time::{Duration, Instant}, }; -const JSON_RPC_SERVER_ERROR_0: i64 = -32000; const NUM_LARGEST_ACCOUNTS: usize = 20; type RpcResponse = Result>; @@ -100,18 +102,13 @@ impl JsonRpcRequestProcessor { .unwrap() .largest_confirmed_root(); debug!("RPC using block: {:?}", cluster_root); - r_bank_forks - .get(cluster_root) - .cloned() - .ok_or_else(|| Error { - code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_0), - message: format!( - "Cluster largest_confirmed_root {} does not exist on node. Node root: {}", - cluster_root, - r_bank_forks.root(), - ), - data: None, - }) + r_bank_forks.get(cluster_root).cloned().ok_or_else(|| { + RpcCustomError::NonexistentClusterRoot { + cluster_root, + node_root: r_bank_forks.root(), + } + .into() + }) } } @@ -421,6 +418,29 @@ impl JsonRpcRequestProcessor { } } + fn check_slot_cleaned_up( + &self, + result: &std::result::Result, + slot: Slot, + ) -> Result<()> + where + T: std::fmt::Debug, + { + if result.is_err() { + if let BlockstoreError::SlotCleanedUp = result.as_ref().unwrap_err() { + return Err(RpcCustomError::BlockCleanedUp { + slot, + first_available_block: self + .blockstore + .get_first_available_block() + .unwrap_or_default(), + } + .into()); + } + } + Ok(()) + } + pub fn get_confirmed_block( &self, slot: Slot, @@ -434,7 +454,9 @@ impl JsonRpcRequestProcessor { .unwrap() .largest_confirmed_root() { - Ok(self.blockstore.get_confirmed_block(slot, encoding).ok()) + let result = self.blockstore.get_confirmed_block(slot, encoding); + self.check_slot_cleaned_up(&result, slot)?; + Ok(result.ok()) } else { Ok(None) } @@ -482,11 +504,9 @@ impl JsonRpcRequestProcessor { let stakes = HashMap::new(); let stakes = bank.epoch_vote_accounts(epoch).unwrap_or(&stakes); - Ok(self - .blockstore - .get_block_time(slot, slot_duration, stakes) - .ok() - .unwrap_or(None)) + let result = self.blockstore.get_block_time(slot, slot_duration, stakes); + self.check_slot_cleaned_up(&result, slot)?; + Ok(result.ok().unwrap_or(None)) } else { Ok(None) } diff --git a/core/src/rpc_error.rs b/core/src/rpc_error.rs new file mode 100644 index 0000000000..ab727776ef --- /dev/null +++ b/core/src/rpc_error.rs @@ -0,0 +1,45 @@ +use jsonrpc_core::{Error, ErrorCode}; +use solana_sdk::clock::Slot; + +const JSON_RPC_SERVER_ERROR_0: i64 = -32000; +const JSON_RPC_SERVER_ERROR_1: i64 = -32001; + +pub enum RpcCustomError { + NonexistentClusterRoot { + cluster_root: Slot, + node_root: Slot, + }, + BlockCleanedUp { + slot: Slot, + first_available_block: Slot, + }, +} + +impl From for Error { + fn from(e: RpcCustomError) -> Self { + match e { + RpcCustomError::NonexistentClusterRoot { + cluster_root, + node_root, + } => Self { + code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_0), + message: format!( + "Cluster largest_confirmed_root {} does not exist on node. Node root: {}", + cluster_root, node_root, + ), + data: None, + }, + RpcCustomError::BlockCleanedUp { + slot, + first_available_block, + } => Self { + code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_1), + message: format!( + "Block {} cleaned up, does not exist on node. First available block: {}", + slot, first_available_block, + ), + data: None, + }, + } + } +}