diff --git a/client/src/rpc_custom_error.rs b/client/src/rpc_custom_error.rs index ed4607cacc..d45b222703 100644 --- a/client/src/rpc_custom_error.rs +++ b/client/src/rpc_custom_error.rs @@ -11,6 +11,7 @@ pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004; pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005; pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006; pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007; +pub const JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: i64 = -32009; pub enum RpcCustomError { BlockCleanedUp { @@ -30,6 +31,9 @@ pub enum RpcCustomError { SlotSkipped { slot: Slot, }, + LongTermStorageSlotSkipped { + slot: Slot, + }, } impl From for Error { @@ -85,6 +89,11 @@ impl From for Error { ), data: None, }, + RpcCustomError::LongTermStorageSlotSkipped { slot } => Self { + code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED), + message: format!("Slot {} was skipped, or missing in long-term storage", slot), + data: None, + }, } } } diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 61d41c0a40..b6f29a6e98 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -665,6 +665,22 @@ impl JsonRpcRequestProcessor { Ok(()) } + fn check_bigtable_result( + &self, + result: &std::result::Result, + ) -> Result<()> + where + T: std::fmt::Debug, + { + if result.is_err() { + let err = result.as_ref().unwrap_err(); + if let solana_storage_bigtable::Error::BlockNotFound(slot) = err { + return Err(RpcCustomError::LongTermStorageSlotSkipped { slot: *slot }.into()); + } + } + Ok(()) + } + pub fn get_confirmed_block( &self, slot: Slot, @@ -683,9 +699,11 @@ impl JsonRpcRequestProcessor { self.check_blockstore_root(&result, slot)?; if result.is_err() { if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage { - return Ok(self + let bigtable_result = self .runtime_handle - .block_on(bigtable_ledger_storage.get_confirmed_block(slot)) + .block_on(bigtable_ledger_storage.get_confirmed_block(slot)); + self.check_bigtable_result(&bigtable_result)?; + return Ok(bigtable_result .ok() .map(|confirmed_block| confirmed_block.encode(encoding))); } @@ -798,9 +816,11 @@ impl JsonRpcRequestProcessor { self.check_blockstore_root(&result, slot)?; if result.is_err() || matches!(result, Ok(None)) { if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage { - return Ok(self + let bigtable_result = self .runtime_handle - .block_on(bigtable_ledger_storage.get_confirmed_block(slot)) + .block_on(bigtable_ledger_storage.get_confirmed_block(slot)); + self.check_bigtable_result(&bigtable_result)?; + return Ok(bigtable_result .ok() .and_then(|confirmed_block| confirmed_block.block_time)); } diff --git a/storage-bigtable/src/lib.rs b/storage-bigtable/src/lib.rs index f808bd0161..8ddae05f36 100644 --- a/storage-bigtable/src/lib.rs +++ b/storage-bigtable/src/lib.rs @@ -334,7 +334,11 @@ impl LedgerStorage { "blocks", slot_to_key(slot), ) - .await?; + .await + .map_err(|err| match err { + bigtable::Error::RowNotFound => Error::BlockNotFound(slot), + _ => err.into(), + })?; Ok(match block_cell_data { bigtable::CellData::Bincode(block) => block.into(), bigtable::CellData::Protobuf(block) => block.try_into().map_err(|_err| { @@ -347,7 +351,11 @@ impl LedgerStorage { let mut bigtable = self.connection.client(); let transaction_info = bigtable .get_bincode_cell::("tx", signature.to_string()) - .await?; + .await + .map_err(|err| match err { + bigtable::Error::RowNotFound => Error::SignatureNotFound, + _ => err.into(), + })?; Ok(transaction_info.into()) } @@ -361,7 +369,11 @@ impl LedgerStorage { // Figure out which block the transaction is located in let TransactionInfo { slot, index, .. } = bigtable .get_bincode_cell("tx", signature.to_string()) - .await?; + .await + .map_err(|err| match err { + bigtable::Error::RowNotFound => Error::SignatureNotFound, + _ => err.into(), + })?; // Load the block and return the transaction let block = self.get_confirmed_block(slot).await?;