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}
51
52impl Request {
53    /// Serialize into a u8 buffer (first 4 bytes = length)
54    pub fn encode(self) -> Result<Vec<u8>, RequestResponseError> {
55        let request_string =
56            serde_json::to_string(&self).map_err(|_| RequestResponseError::EncodingFailed)?;
57        let request_bytes = request_string.as_bytes();
58        let request_length = request_bytes.len();
59
60        if request_length > u32::MAX as usize {
61            return Err(RequestResponseError::MalformedData);
62        }
63
64        let mut buf = vec![0u8; request_length + 4];
65        buf[0..4].copy_from_slice(&(request_length as u32).to_be_bytes());
66        buf[4..].copy_from_slice(request_bytes);
67
68        Ok(buf)
69    }
70
71    /// Blocking deserialize from TcpStream
72    pub async fn decode_from_stream(stream: &mut TcpStream) -> Result<Self, RequestResponseError> {
73        let mut size_buf = [0u8; 4];
74        stream
75            .read_exact(&mut size_buf)
76            .await
77            .map_err(|_| RequestResponseError::Stream)?;
78
79        let request_size = u32::from_be_bytes(size_buf) as usize;
80        let mut request_buf = vec![0u8; request_size];
81
82        stream
83            .read_exact(&mut request_buf)
84            .await
85            .map_err(|_| RequestResponseError::Stream)?;
86
87        let request: Request = serde_json::from_slice(&request_buf)
88            .map_err(|_| RequestResponseError::DecodingFailed)?;
89
90        Ok(request)
91    }
92}
93
94#[derive(Serialize, Deserialize)]
95pub enum Response {
96    Height {
97        height: u64,
98    },
99    Block {
100        block: Option<Block>,
101    },
102    Difficulty {
103        transaction_difficulty: [u8; 32],
104        block_difficulty: [u8; 32],
105    },
106    BlockHash {
107        hash: Option<Hash>,
108    },
109    BlockHeight {
110        height: Option<usize>,
111    },
112    Transaction {
113        transaction: Option<Transaction>,
114    },
115    TransactionsOfAddress {
116        transactions: Vec<TransactionId>,
117        next_page: Option<u32>,
118    },
119    AvailableUTXOs {
120        available_inputs: Vec<(TransactionId, TransactionOutput, usize)>,
121        next_page: Option<u32>,
122    },
123    Balance {
124        balance: u64,
125    },
126    Reward {
127        reward: u64,
128    },
129    Peers {
130        peers: Vec<SocketAddr>,
131    },
132    Mempool {
133        mempool: Vec<Transaction>,
134        next_page: Option<u32>,
135    },
136    NewBlock {
137        status: Result<(), BlockchainError>,
138    },
139    NewTransaction {
140        status: Result<(), BlockchainError>,
141    },
142}
143
144impl Response {
145    /// Serialize into a u8 buffer (first 2 bytes = length)
146    pub fn encode(self) -> Result<Vec<u8>, RequestResponseError> {
147        let response_string =
148            serde_json::to_string(&self).map_err(|_| RequestResponseError::EncodingFailed)?;
149        let response_bytes = response_string.as_bytes();
150        let response_length = response_bytes.len();
151
152        if response_length > u16::MAX as usize {
153            return Err(RequestResponseError::MalformedData);
154        }
155
156        let mut buf = vec![0u8; response_length + 2];
157        buf[0..2].copy_from_slice(&(response_length as u16).to_be_bytes());
158        buf[2..].copy_from_slice(response_bytes);
159
160        Ok(buf)
161    }
162
163    /// Blocking deserialize from TcpStream
164    pub async fn decode_from_stream(stream: &mut TcpStream) -> Result<Self, RequestResponseError> {
165        let mut size_buf = [0u8; 2];
166        stream
167            .read_exact(&mut size_buf)
168            .await
169            .map_err(|_| RequestResponseError::Stream)?;
170
171        let response_size = u16::from_be_bytes(size_buf) as usize;
172        let mut response_buf = vec![0u8; response_size];
173
174        stream
175            .read_exact(&mut response_buf)
176            .await
177            .map_err(|_| RequestResponseError::Stream)?;
178
179        let response: Response = serde_json::from_slice(&response_buf)
180            .map_err(|_| RequestResponseError::DecodingFailed)?;
181
182        Ok(response)
183    }
184}