Rpc: Add custom error for BigTable data not found (#14762)
* Expose not-found bigtable error * Add custom rpc error for bigtable data not found * Return custom rpc error when bigtable block is not found * Generalize long-term storage
This commit is contained in:
		@@ -12,6 +12,7 @@ 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_NO_SNAPSHOT: i64 = -32008;
 | 
			
		||||
pub const JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: i64 = -32009;
 | 
			
		||||
 | 
			
		||||
pub enum RpcCustomError {
 | 
			
		||||
    BlockCleanedUp {
 | 
			
		||||
@@ -34,6 +35,9 @@ pub enum RpcCustomError {
 | 
			
		||||
        slot: Slot,
 | 
			
		||||
    },
 | 
			
		||||
    NoSnapshot,
 | 
			
		||||
    LongTermStorageSlotSkipped {
 | 
			
		||||
        slot: Slot,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Serialize, Deserialize)]
 | 
			
		||||
@@ -106,6 +110,11 @@ impl From<RpcCustomError> for Error {
 | 
			
		||||
                message: "No snapshot".to_string(),
 | 
			
		||||
                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,
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -670,6 +670,22 @@ impl JsonRpcRequestProcessor {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn check_bigtable_result<T>(
 | 
			
		||||
        &self,
 | 
			
		||||
        result: &std::result::Result<T, solana_storage_bigtable::Error>,
 | 
			
		||||
    ) -> 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,
 | 
			
		||||
@@ -688,9 +704,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)));
 | 
			
		||||
                }
 | 
			
		||||
@@ -803,9 +821,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));
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -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::<TransactionInfo>("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?;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user