snap_coin/api/
requests.rs

1use std::net::SocketAddr;
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5use tokio::{io::AsyncReadExt, net::TcpStream};
6
7use crate::{
8    core::{
9        block::Block,
10        blockchain::BlockchainError,
11        transaction::{Transaction, TransactionId, TransactionOutput},
12    },
13    crypto::{Hash, keys::Public},
14};
15
16#[derive(Error, Debug, Serialize, Deserialize)]
17pub enum RequestResponseError {
18    #[error("Failed to deserialize message")]
19    DecodingFailed,
20
21    #[error("Failed to serialize message")]
22    EncodingFailed,
23
24    #[error("Malformed data error")]
25    MalformedData,
26
27    #[error("Stream error")]
28    Stream,
29
30    #[error("Request returned invalid response")]
31    IncorrectResponse,
32}
33
34#[derive(Serialize, Deserialize)]
35pub enum Request {
36    Height,
37    Block { block_hash: Hash },
38    Difficulty,
39    BlockHash { height: u64 },
40    BlockHeight { hash: Hash },
41    Transaction { transaction_id: TransactionId },
42    TransactionsOfAddress { address: Public, page: u32 },
43    AvailableUTXOs { address: Public, page: u32 },
44    Balance { address: Public },
45    Reward,
46    Peers,
47    Mempool { page: u32 },
48    NewBlock { new_block: Block },
49    NewTransaction { new_transaction: Transaction },
50    LiveTransactionDifficulty,
51}
52
53impl Request {
54    /// Serialize into a u8 buffer (first 4 bytes = length)
55    pub fn encode(self) -> Result<Vec<u8>, RequestResponseError> {
56        let request_string =
57            serde_json::to_string(&self).map_err(|_| RequestResponseError::EncodingFailed)?;
58        let request_bytes = request_string.as_bytes();
59        let request_length = request_bytes.len();
60
61        if request_length > u32::MAX as usize {
62            return Err(RequestResponseError::MalformedData);
63        }
64
65        let mut buf = vec![0u8; request_length + 4];
66        buf[0..4].copy_from_slice(&(request_length as u32).to_be_bytes());
67        buf[4..].copy_from_slice(request_bytes);
68
69        Ok(buf)
70    }
71
72    /// Blocking deserialize from TcpStream
73    pub async fn decode_from_stream(stream: &mut TcpStream) -> Result<Self, RequestResponseError> {
74        let mut size_buf = [0u8; 4];
75        stream
76            .read_exact(&mut size_buf)
77            .await
78            .map_err(|_| RequestResponseError::Stream)?;
79
80        let request_size = u32::from_be_bytes(size_buf) as usize;
81        let mut request_buf = vec![0u8; request_size];
82
83        stream
84            .read_exact(&mut request_buf)
85            .await
86            .map_err(|_| RequestResponseError::Stream)?;
87
88        let request: Request = serde_json::from_slice(&request_buf)
89            .map_err(|_| RequestResponseError::DecodingFailed)?;
90
91        Ok(request)
92    }
93}
94
95#[derive(Serialize, Deserialize)]
96pub enum Response {
97    Height {
98        height: u64,
99    },
100    Block {
101        block: Option<Block>,
102    },
103    Difficulty {
104        transaction_difficulty: [u8; 32],
105        block_difficulty: [u8; 32],
106    },
107    BlockHash {
108        hash: Option<Hash>,
109    },
110    BlockHeight {
111        height: Option<usize>,
112    },
113    Transaction {
114        transaction: Option<Transaction>,
115    },
116    TransactionsOfAddress {
117        transactions: Vec<TransactionId>,
118        next_page: Option<u32>,
119    },
120    AvailableUTXOs {
121        available_inputs: Vec<(TransactionId, TransactionOutput, usize)>,
122        next_page: Option<u32>,
123    },
124    Balance {
125        balance: u64,
126    },
127    Reward {
128        reward: u64,
129    },
130    Peers {
131        peers: Vec<SocketAddr>,
132    },
133    Mempool {
134        mempool: Vec<Transaction>,
135        next_page: Option<u32>,
136    },
137    NewBlock {
138        status: Result<(), BlockchainError>,
139    },
140    NewTransaction {
141        status: Result<(), BlockchainError>,
142    },
143    LiveTransactionDifficulty {
144        live_difficulty: [u8; 32],
145    },
146}
147
148impl Response {
149    /// Serialize into a u8 buffer (first 4 bytes = length)
150    pub fn encode(self) -> Result<Vec<u8>, RequestResponseError> {
151        let response_string =
152            serde_json::to_string(&self).map_err(|_| RequestResponseError::EncodingFailed)?;
153        let response_bytes = response_string.as_bytes();
154        let response_length = response_bytes.len();
155
156        if response_length > u32::MAX as usize {
157            return Err(RequestResponseError::MalformedData);
158        }
159
160        let mut buf = vec![0u8; response_length + 4];
161        buf[0..4].copy_from_slice(&(response_length as u32).to_be_bytes());
162        buf[4..].copy_from_slice(response_bytes);
163
164        Ok(buf)
165    }
166
167    /// Blocking deserialize from TcpStream
168    pub async fn decode_from_stream(stream: &mut TcpStream) -> Result<Self, RequestResponseError> {
169        let mut size_buf = [0u8; 4];
170        stream
171            .read_exact(&mut size_buf)
172            .await
173            .map_err(|_| RequestResponseError::Stream)?;
174
175        let response_size = u32::from_be_bytes(size_buf) as usize;
176        let mut response_buf = vec![0u8; response_size];
177
178        stream
179            .read_exact(&mut response_buf)
180            .await
181            .map_err(|_| RequestResponseError::Stream)?;
182
183        let response: Response = serde_json::from_slice(&response_buf)
184            .map_err(|_| RequestResponseError::DecodingFailed)?;
185
186        Ok(response)
187    }
188}