diff --git a/rpc/types/src/misc/status.rs b/rpc/types/src/misc/status.rs
index 297addee..c402258e 100644
--- a/rpc/types/src/misc/status.rs
+++ b/rpc/types/src/misc/status.rs
@@ -47,8 +47,11 @@ use crate::constants::{
 /// assert_eq!(to_string(&other).unwrap(),                   r#""OTHER""#);
 ///
 /// assert_eq!(Status::Ok.as_ref(),              CORE_RPC_STATUS_OK);
+/// assert_eq!("Ok",                             CORE_RPC_STATUS_OK);
 /// assert_eq!(Status::Failed.as_ref(),          CORE_RPC_STATUS_FAILED);
+/// assert_eq!("FAILED",                         CORE_RPC_STATUS_FAILED);
 /// assert_eq!(Status::Busy.as_ref(),            CORE_RPC_STATUS_BUSY);
+/// assert_eq!("Busy",                           CORE_RPC_STATUS_BUSY);
 /// assert_eq!(Status::NotMining.as_ref(),       CORE_RPC_STATUS_NOT_MINING);
 /// assert_eq!(Status::PaymentRequired.as_ref(), CORE_RPC_STATUS_PAYMENT_REQUIRED);
 /// assert_eq!(other.as_ref(),                   "OTHER");
@@ -74,16 +77,16 @@ pub enum Status {
     // `#[serde(rename = "")]` only takes raw string literals?
     // We have to re-type the constants here...
     /// Successful RPC response, everything is OK; [`CORE_RPC_STATUS_OK`].
-    #[cfg_attr(feature = "serde", serde(rename = "OK"))]
+    #[cfg_attr(feature = "serde", serde(rename = "OK", alias = "Ok"))]
     #[default]
     Ok,
 
     /// Generic request failure.
-    #[cfg_attr(feature = "serde", serde(rename = "Failed"))]
+    #[cfg_attr(feature = "serde", serde(alias = "FAILED"))]
     Failed,
 
     /// The daemon is busy, try later; [`CORE_RPC_STATUS_BUSY`].
-    #[cfg_attr(feature = "serde", serde(rename = "BUSY"))]
+    #[cfg_attr(feature = "serde", serde(rename = "BUSY", alias = "Busy"))]
     Busy,
 
     /// The daemon is not mining; [`CORE_RPC_STATUS_NOT_MINING`].
diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs
index e58bbb19..3ae2be40 100644
--- a/rpc/types/src/other.rs
+++ b/rpc/types/src/other.rs
@@ -785,7 +785,7 @@ mod test {
             SendRawTransactionResponse {
                 base: AccessResponseBase {
                     response_base: ResponseBase {
-                        status: Status::Other("Failed".into()),
+                        status: Status::Failed,
                         untrusted: false,
                     },
                     credits: 0,
diff --git a/storage/blockchain/src/ops/output.rs b/storage/blockchain/src/ops/output.rs
index 9f9d1a3f..4ae24c9d 100644
--- a/storage/blockchain/src/ops/output.rs
+++ b/storage/blockchain/src/ops/output.rs
@@ -2,7 +2,7 @@
 
 //---------------------------------------------------------------------------------------------------- Import
 use curve25519_dalek::edwards::CompressedEdwardsY;
-use monero_serai::transaction::Timelock;
+use monero_serai::transaction::{Timelock, Transaction};
 
 use cuprate_database::{
     DbResult, RuntimeError, {DatabaseRo, DatabaseRw},
@@ -13,7 +13,9 @@ use cuprate_types::OutputOnChain;
 
 use crate::{
     ops::macros::{doc_add_block_inner_invariant, doc_error},
-    tables::{BlockTxsHashes, Outputs, RctOutputs, Tables, TablesMut, TxUnlockTime},
+    tables::{
+        BlockInfos, BlockTxsHashes, Outputs, RctOutputs, Tables, TablesMut, TxBlobs, TxUnlockTime,
+    },
     types::{Amount, AmountIndex, Output, OutputFlags, PreRctOutputId, RctOutput},
 };
 
@@ -154,6 +156,8 @@ pub fn output_to_output_on_chain(
     amount: Amount,
     table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
     table_block_txs_hashes: &impl DatabaseRo<BlockTxsHashes>,
+    table_block_infos: &impl DatabaseRo<BlockInfos>,
+    table_tx_blobs: &impl DatabaseRo<TxBlobs>,
 ) -> DbResult<OutputOnChain> {
     let commitment = compute_zero_commitment(amount);
 
@@ -173,7 +177,13 @@ pub fn output_to_output_on_chain(
     let txid = {
         let height = u32_to_usize(output.height);
         let tx_idx = u64_to_usize(output.tx_idx);
-        table_block_txs_hashes.get(&height)?[tx_idx]
+        if let Some(hash) = table_block_txs_hashes.get(&height)?.get(tx_idx) {
+            *hash
+        } else {
+            let miner_tx_id = table_block_infos.get(&height)?.mining_tx_index;
+            let tx_blob = table_tx_blobs.get(&miner_tx_id)?;
+            Transaction::read(&mut tx_blob.0.as_slice())?.hash()
+        }
     };
 
     Ok(OutputOnChain {
@@ -198,6 +208,8 @@ pub fn rct_output_to_output_on_chain(
     rct_output: &RctOutput,
     table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
     table_block_txs_hashes: &impl DatabaseRo<BlockTxsHashes>,
+    table_block_infos: &impl DatabaseRo<BlockInfos>,
+    table_tx_blobs: &impl DatabaseRo<TxBlobs>,
 ) -> DbResult<OutputOnChain> {
     // INVARIANT: Commitments stored are valid when stored by the database.
     let commitment = CompressedEdwardsY::from_slice(&rct_output.commitment)
@@ -221,7 +233,13 @@ pub fn rct_output_to_output_on_chain(
     let txid = {
         let height = u32_to_usize(rct_output.height);
         let tx_idx = u64_to_usize(rct_output.tx_idx);
-        table_block_txs_hashes.get(&height)?[tx_idx]
+        if let Some(hash) = table_block_txs_hashes.get(&height)?.get(tx_idx) {
+            *hash
+        } else {
+            let miner_tx_id = table_block_infos.get(&height)?.mining_tx_index;
+            let tx_blob = table_tx_blobs.get(&miner_tx_id)?;
+            Transaction::read(&mut tx_blob.0.as_slice())?.hash()
+        }
     };
 
     Ok(OutputOnChain {
@@ -245,6 +263,8 @@ pub fn id_to_output_on_chain(id: &PreRctOutputId, tables: &impl Tables) -> DbRes
             &rct_output,
             tables.tx_unlock_time(),
             tables.block_txs_hashes(),
+            tables.block_infos(),
+            tables.tx_blobs(),
         )?;
 
         Ok(output_on_chain)
@@ -256,6 +276,8 @@ pub fn id_to_output_on_chain(id: &PreRctOutputId, tables: &impl Tables) -> DbRes
             id.amount,
             tables.tx_unlock_time(),
             tables.block_txs_hashes(),
+            tables.block_infos(),
+            tables.tx_blobs(),
         )?;
 
         Ok(output_on_chain)
diff --git a/types/hex/README.md b/types/hex/README.md
index 2e0310bb..66499137 100644
--- a/types/hex/README.md
+++ b/types/hex/README.md
@@ -1,7 +1,2 @@
 # `cuprate-hex`
-Cuprate's hexadecimal data types.
-
-# Features flags
-| Feature flag | Does what |
-|--------------|-----------|
-| `serde`      | Enables `serde` on types where applicable
\ No newline at end of file
+Cuprate's hexadecimal data types.
\ No newline at end of file
diff --git a/types/hex/src/prefix.rs b/types/hex/src/prefix.rs
deleted file mode 100644
index 8b137891..00000000
--- a/types/hex/src/prefix.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/types/hex/src/vec.rs b/types/hex/src/vec.rs
index 2dfd9135..9c39873e 100644
--- a/types/hex/src/vec.rs
+++ b/types/hex/src/vec.rs
@@ -11,18 +11,18 @@ use serde::{Deserialize, Deserializer, Serialize};
 /// ```rust
 /// # use cuprate_hex::HexVec;
 /// let hash = [1; 32];
-/// let hex_bytes = HexVec(hash);
+/// let hex_vec = HexVec(hash);
 /// let expected_json = r#""0101010101010101010101010101010101010101010101010101010101010101""#;
 ///
-/// let to_string = serde_json::to_string(&hex_bytes).unwrap();
+/// let to_string = serde_json::to_string(&hex_vec).unwrap();
 /// assert_eq!(to_string, expected_json);
 ///
 /// let from_str = serde_json::from_str::<HexVec>(expected_json).unwrap();
-/// assert_eq!(hex_bytes, from_str);
+/// assert_eq!(hex_vec, from_str);
 ///
 /// //------
 ///
-/// let vec = vec![hex_bytes; 2];
+/// let vec = vec![hex_vec; 2];
 /// let expected_json = r#"["0101010101010101010101010101010101010101010101010101010101010101","0101010101010101010101010101010101010101010101010101010101010101"]"#;
 ///
 /// let to_string = serde_json::to_string(&vec).unwrap();
@@ -47,7 +47,14 @@ impl HexVec {
         self.0.is_empty()
     }
 
-    /// TODO
+    /// Returns an empty [`Self`] if `array` is all `0`s.
+    ///
+    /// ```rust
+    /// # use cuprate_hex::HexVec;
+    /// assert_eq!(HexVec::empty_if_zeroed([1; 32]), [1; 32]);
+    /// assert_eq!(HexVec::empty_if_zeroed([0; 32]), HexVec(vec![]));
+    /// assert!(HexVec::empty_if_zeroed([0; 32]).is_empty());
+    /// ```
     pub fn empty_if_zeroed<const N: usize>(array: [u8; N]) -> Self {
         if array == [0; N] {
             Self(Vec::new())
@@ -112,13 +119,13 @@ mod test {
     #[test]
     fn asdf() {
         let hash = vec![0; 32];
-        let hex_bytes = HexVec(hash);
+        let hex_vec = HexVec(hash);
         let expected_json = r#""0000000000000000000000000000000000000000000000000000000000000000""#;
 
-        let to_string = serde_json::to_string(&hex_bytes).unwrap();
+        let to_string = serde_json::to_string(&hex_vec).unwrap();
         assert_eq!(to_string, expected_json);
 
         let from_str = serde_json::from_str::<HexVec>(expected_json).unwrap();
-        assert_eq!(hex_bytes, from_str);
+        assert_eq!(hex_vec, from_str);
     }
 }