diff --git a/src/database.rs b/src/database.rs index f97efbb..0e8bb04 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1084,11 +1084,8 @@ impl Database { #[instrument(skip(self, block_id))] pub async fn block_by_id(&self, block_id: &[u8]) -> Result, Error> { - // query for the block if it exists - let str = format!( - "SELECT * FROM {}.{BLOCKS_TABLE_NAME} WHERE block_id=$1", - self.network - ); + let str = format!("SELECT b.*, txs FROM {0}.blocks b LEFT JOIN (SELECT block_id, JSON_AGG(JSON_BUILD_OBJECT('hash_id', encode(t.hash, 'hex'), 'tx_type', t.tx_type)) AS txs FROM {0}.transactions t GROUP BY t.block_id) t ON b.block_id = t.block_id WHERE b.block_id = $1;", self.network); + query(&str) .bind(block_id) .fetch_optional(&*self.pool) @@ -1099,12 +1096,10 @@ impl Database { /// Returns the block at `block_height` if present, otherwise returns an Error. #[instrument(skip(self))] pub async fn block_by_height(&self, block_height: u32) -> Result, Error> { - let str = format!( - "SELECT * FROM {}.{BLOCKS_TABLE_NAME} WHERE header_height={block_height}", - self.network - ); + let str = format!("SELECT b.*, txs FROM {0}.blocks b LEFT JOIN (SELECT block_id, JSON_AGG(JSON_BUILD_OBJECT('hash_id', encode(t.hash, 'hex'), 'tx_type', t.tx_type)) AS txs FROM {0}.transactions t GROUP BY t.block_id) t ON b.block_id = t.block_id WHERE b.header_height = $1;", self.network); query(&str) + .bind(block_height as i32) .fetch_optional(&*self.pool) .await .map_err(Error::from) @@ -1113,7 +1108,7 @@ impl Database { #[instrument(skip(self))] /// Returns the latest block, otherwise returns an Error. pub async fn get_last_block(&self) -> Result { - let str = format!("SELECT * FROM {0}.{BLOCKS_TABLE_NAME} WHERE header_height = (SELECT MAX(header_height) FROM {0}.{BLOCKS_TABLE_NAME})", self.network); + let str = format!("SELECT b.*, txs FROM {0}.blocks b LEFT JOIN (SELECT block_id, JSON_AGG(JSON_BUILD_OBJECT('hash_id', encode(t.hash, 'hex'), 'tx_type', t.tx_type)) AS txs FROM {0}.transactions t GROUP BY t.block_id) t ON b.block_id = t.block_id WHERE b.header_height = (SELECT MAX(header_height) FROM {0}.blocks);", self.network); // use query_one as the row matching max height is unique. query(&str) @@ -1406,7 +1401,7 @@ impl Database { num: &i32, offset: Option<&i32>, ) -> Result, Error> { - let str = format!("SELECT * FROM {0}.{BLOCKS_TABLE_NAME} ORDER BY header_height DESC LIMIT {1} OFFSET {2};", self.network, num, offset.unwrap_or(& 0)); + let str = format!("SELECT b.*, t.txs FROM {0}.blocks b LEFT JOIN (SELECT block_id, JSON_AGG(JSON_BUILD_OBJECT('hash_id', encode(t.hash, 'hex'), 'tx_type', t.tx_type)) AS txs FROM {0}.transactions t GROUP BY t.block_id) t ON b.block_id = t.block_id ORDER BY b.header_height DESC LIMIT {1} OFFSET {2};", self.network, num, offset.unwrap_or(& 0)); // use query_one as the row matching max height is unique. query(&str) diff --git a/src/server/blocks.rs b/src/server/blocks.rs index 63528ff..e3e5f18 100644 --- a/src/server/blocks.rs +++ b/src/server/blocks.rs @@ -220,6 +220,14 @@ impl TryFrom<&Row> for BlockInfo { let last_commit = LastCommitInfo::read_from(row)?; + // tx hashes + let txs: Option = row.try_get("txs")?; + let tx_hashes: Vec = if let Some(txs) = txs { + serde_json::from_value(txs)? + } else { + vec![] + }; + let header = Header { version, chain_id, @@ -241,7 +249,7 @@ impl TryFrom<&Row> for BlockInfo { block_id: HashID(block_id), header, last_commit, - tx_hashes: vec![], + tx_hashes, }) } } diff --git a/src/server/endpoints/block.rs b/src/server/endpoints/block.rs index f6d91d0..7ed1f63 100644 --- a/src/server/endpoints/block.rs +++ b/src/server/endpoints/block.rs @@ -3,14 +3,10 @@ use axum::{ Json, }; use serde::{Deserialize, Serialize}; -use sqlx::Row as TRow; use std::collections::HashMap; use tracing::info; -use crate::{ - server::{blocks::HashID, blocks::TxShort, ServerState}, - BlockInfo, Error, -}; +use crate::{server::ServerState, BlockInfo, Error}; #[derive(Debug, Serialize, Deserialize, PartialEq)] #[serde(untagged)] @@ -24,25 +20,6 @@ pub struct LatestBlocks { pub blocks: Vec, } -async fn get_tx_hashes( - state: &ServerState, - block: &mut BlockInfo, - hash: &[u8], -) -> Result<(), Error> { - let rows = state.db.get_tx_hashes_block(hash).await?; - - let mut tx_hashes: Vec = vec![]; - for row in rows.iter() { - let hash_id = HashID(row.try_get("hash")?); - let tx_type: String = row.try_get("tx_type")?; - tx_hashes.push(TxShort { tx_type, hash_id }); - } - - block.tx_hashes = tx_hashes; - - Ok(()) -} - pub async fn get_block_by_hash( State(state): State, Path(hash): Path, @@ -55,10 +32,7 @@ pub async fn get_block_by_hash( let Some(row) = row else { return Ok(Json(None)); }; - let mut block = BlockInfo::try_from(&row)?; - - let block_id: Vec = row.try_get("block_id")?; - get_tx_hashes(&state, &mut block, &block_id).await?; + let block = BlockInfo::try_from(&row)?; Ok(Json(Some(block))) } @@ -74,10 +48,7 @@ pub async fn get_block_by_height( return Ok(Json(None)); }; - let mut block = BlockInfo::try_from(&row)?; - - let block_id: Vec = row.try_get("block_id")?; - get_tx_hashes(&state, &mut block, &block_id).await?; + let block = BlockInfo::try_from(&row)?; Ok(Json(Some(block))) } @@ -96,10 +67,7 @@ pub async fn get_last_block( let mut blocks: LatestBlocks = LatestBlocks { blocks: vec![] }; for row in rows { - let mut block = BlockInfo::try_from(&row)?; - - let block_id: Vec = row.try_get("block_id")?; - get_tx_hashes(&state, &mut block, &block_id).await?; + let block = BlockInfo::try_from(&row)?; blocks.blocks.push(block); } @@ -108,10 +76,7 @@ pub async fn get_last_block( } else { let row = state.db.get_last_block().await?; - let mut block = BlockInfo::try_from(&row)?; - - let block_id: Vec = row.try_get("block_id")?; - get_tx_hashes(&state, &mut block, &block_id).await?; + let block = BlockInfo::try_from(&row)?; Ok(Json(LatestBlock::LastBlock(Box::new(block)))) }