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