From efe62559c798a34f5c3f8d6352ef79a3c114f0da Mon Sep 17 00:00:00 2001 From: Artur <33733651+Keeqler@users.noreply.github.com> Date: Thu, 15 May 2025 12:44:34 -0300 Subject: [PATCH] Better responses --- src/main.rs | 118 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2f29193..83d095f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,69 +1,131 @@ -use std::sync::Mutex; use cuprate_blockchain::{config::ConfigBuilder, ops, tables::{OpenTables, Tables}} ; use cuprate_database::{ConcreteEnv, DatabaseRo, Env, EnvInner}; -use cuprate_types::json::tx::Transaction; use hex::FromHex; -use actix_web::{get, web, App, HttpServer, Responder}; +use actix_web::{get, web::{self}, App, HttpServer, Responder}; use serde::Serialize; -struct EnvState { env: Mutex } +#[derive(Serialize)] +struct TransactionOutput { + pub amount: u64, + pub public_key: String, +} + +#[derive(Serialize)] +struct TransactionResponse { + pub hash: String, + pub version: u8, + pub is_coinbase: bool, + pub confirmation_height: usize, + pub timestamp: u64, + pub weight: usize, + pub inputs: Vec, + pub outputs: Vec, + pub extra: String, +} #[get("/api/tx/{tx_hash}")] async fn get_tx( - env_state: web::Data, + env: web::Data, tx_hash: web::Path ) -> std::io::Result { - let tx_hash_buff = <[u8; 32]>::from_hex(tx_hash.to_string()) + let tx_hash_buff = <[u8; 32]>::from_hex(tx_hash.clone().to_string()) .unwrap(); - let env = env_state.env.lock().unwrap(); let env_inner = env.env_inner(); let tx_ro = env_inner.tx_ro().unwrap(); let tables = env_inner.open_tables(&tx_ro).unwrap(); + + let tx_id = tables.tx_ids().get(&tx_hash_buff).unwrap(); + let tx = ops::tx::get_tx_from_id(&tx_id, tables.tx_blobs()).unwrap(); + let tx_height = tables.tx_heights().get(&tx_id).unwrap(); + let tx_block = tables.block_infos().get(&tx_height).unwrap(); + let tx_prefix = tx.prefix(); - let tx = ops::tx::get_tx( - &tx_hash_buff, - tables.tx_ids(), - tables.tx_blobs() - ) - .unwrap(); + let mut outputs: Vec = Vec::with_capacity(tx_prefix.outputs.len()); - let response: Transaction = tx.into(); + for o in &tx_prefix.outputs { + outputs.push(TransactionOutput { + amount: o.amount.unwrap(), + public_key: hex::encode(o.key.to_bytes()) + }) + } + + let response = TransactionResponse { + hash: tx_hash.clone(), + version: tx.version(), + is_coinbase: tx_prefix.inputs.len() == 0, + confirmation_height: tx_height, + timestamp: tx_block.timestamp, + weight: tx.weight(), + inputs: Vec::with_capacity(0), + outputs, + extra: hex::encode(tx_prefix.extra.clone()), + }; Ok(web::Json(response)) } #[derive(Serialize)] -struct BlockResponse { - pub timestamp: u64, - pub cumulative_generated_coins: u64, +struct BlockTransactionResponse { + pub hash: String, + pub version: u8, + pub is_coinbase: bool, pub weight: usize, + pub inputs: Vec, + pub outputs: Vec, + pub extra: String, +} + +#[derive(Serialize)] +struct BlockResponse { + pub hash: String, + pub timestamp: u64, + pub weight: usize, + pub cumulative_generated_coins: u64, pub cumulative_difficulty_low: u64, pub cumulative_difficulty_high: u64, - pub hash: String, pub cumulative_rct_outs: u64, pub long_term_weight: usize, - pub tx_hashes: Vec, + pub transactions: Vec, } #[get("/api/block/{height}")] async fn get_block( - env_state: web::Data, + env: web::Data, height: web::Path ) -> std::io::Result { - let env = env_state.env.lock().unwrap(); let env_inner = env.env_inner(); let tx_ro = env_inner.tx_ro().unwrap(); let tables = env_inner.open_tables(&tx_ro).unwrap(); let height = height.parse::().ok().unwrap(); let block_info = ops::block::get_block_info(&height, tables.block_infos()).unwrap(); - let block_tx_hashes = tables.block_txs_hashes().get(&height).unwrap(); - let block_tx_num = block_tx_hashes.len(); - let mut tx_hashes: Vec = Vec::with_capacity(block_tx_num); + let block_tx_hashes = tables.block_txs_hashes().get(&height).unwrap(); + let mut transactions: Vec = Vec::with_capacity(block_tx_hashes.len()); + + for tx_hash in block_tx_hashes.iter() { + let tx = ops::tx::get_tx(&tx_hash, tables.tx_ids(), tables.tx_blobs()).unwrap(); + let tx_prefix = tx.prefix(); + let mut outputs: Vec = Vec::with_capacity(tx_prefix.outputs.len()); + + for o in &tx_prefix.outputs { + outputs.push(TransactionOutput { + amount: o.amount.unwrap(), + public_key: hex::encode(o.key.to_bytes()) + }) + } + + transactions.push(BlockTransactionResponse { + hash: hex::encode(tx.hash()), + version: tx.version(), + is_coinbase: true, + weight: tx.weight(), + inputs: Vec::with_capacity(0), + outputs: outputs, + extra: hex::encode(tx_prefix.extra.clone()), + }); - for tx_id_bytes in block_tx_hashes.iter() { - tx_hashes.push(hex::encode(&tx_id_bytes)); + break; } let response = BlockResponse { @@ -75,7 +137,7 @@ async fn get_block( hash: hex::encode(&block_info.block_hash), cumulative_rct_outs: block_info.cumulative_rct_outs, long_term_weight: block_info.long_term_weight, - tx_hashes, + transactions, }; Ok(web::Json(response)) @@ -91,7 +153,7 @@ async fn main() -> std::io::Result<()> { .build(); let env = cuprate_blockchain::open(config).unwrap(); - let env_state = web::Data::new(EnvState { env: env.into() }); + let env_state = web::Data::new(env); HttpServer::new(move || { App::new()