snap_coin/api/
requests.rs1use 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 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 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 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 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}