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