Skip to main content

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