From dff77e8bed68f6d0ec529fb90647526903a5fc76 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 19 Dec 2024 18:10:43 -0500 Subject: [PATCH] fix `get_txid` for `/get_outs` miner transaction was not accounted for --- rpc/types/src/misc/status.rs | 9 ++++++--- rpc/types/src/other.rs | 2 +- storage/blockchain/src/ops/output.rs | 30 ++++++++++++++++++++++++---- types/hex/README.md | 7 +------ types/hex/src/prefix.rs | 1 - types/hex/src/vec.rs | 23 +++++++++++++-------- 6 files changed, 49 insertions(+), 23 deletions(-) delete mode 100644 types/hex/src/prefix.rs 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, table_block_txs_hashes: &impl DatabaseRo, + table_block_infos: &impl DatabaseRo, + table_tx_blobs: &impl DatabaseRo, ) -> DbResult { 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, table_block_txs_hashes: &impl DatabaseRo, + table_block_infos: &impl DatabaseRo, + table_tx_blobs: &impl DatabaseRo, ) -> DbResult { // 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::(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(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::(expected_json).unwrap(); - assert_eq!(hex_bytes, from_str); + assert_eq!(hex_vec, from_str); } }