Skip to main content

sv1_api/
utils.rs

1use crate::error::{self, Error};
2use binary_sv2::{B032, U256};
3use bitcoin_hashes::hex::{FromHex, ToHex};
4use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::fmt;
8use std::{convert::TryFrom, mem::size_of, ops::BitAnd};
9
10/// Helper type that allows simple serialization and deserialization of byte vectors
11/// that are represented as hex strings in JSON.
12/// Extranonce must be less than or equal to 32 bytes.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Extranonce<'a>(pub B032<'a>);
15
16impl fmt::Display for Extranonce<'_> {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.write_str(&self.0.inner_as_ref().to_hex())
19    }
20}
21
22impl Extranonce<'_> {
23    pub fn len(&self) -> usize {
24        self.0.inner_as_ref().len()
25    }
26    pub fn is_empty(&self) -> bool {
27        self.0.inner_as_ref().is_empty()
28    }
29}
30
31impl<'a> TryFrom<Vec<u8>> for Extranonce<'a> {
32    type Error = Error<'a>;
33    fn try_from(value: Vec<u8>) -> Result<Self, Error<'a>> {
34        Ok(Extranonce(B032::try_from(value)?))
35    }
36}
37
38impl<'a> From<Extranonce<'a>> for Vec<u8> {
39    fn from(v: Extranonce<'a>) -> Self {
40        v.0.to_vec()
41    }
42}
43
44impl<'a> From<Extranonce<'a>> for Value {
45    fn from(eb: Extranonce<'a>) -> Self {
46        Into::<String>::into(eb).into()
47    }
48}
49
50/// fix for error on odd-length hex sequences
51/// FIXME: find a nicer solution
52fn hex_decode(s: &str) -> Result<Vec<u8>, Error<'static>> {
53    if s.len() % 2 != 0 {
54        Vec::<u8>::from_hex(&format!("0{s}")).map_err(Error::HexError)
55    } else {
56        Vec::<u8>::from_hex(s).map_err(Error::HexError)
57    }
58}
59
60impl<'a> TryFrom<&str> for Extranonce<'a> {
61    type Error = error::Error<'a>;
62
63    fn try_from(value: &str) -> Result<Self, Error<'a>> {
64        Ok(Extranonce(B032::try_from(hex_decode(value)?)?))
65    }
66}
67
68impl<'a> From<Extranonce<'a>> for String {
69    fn from(bytes: Extranonce<'a>) -> String {
70        bytes.0.inner_as_ref().to_hex()
71    }
72}
73
74impl BitAnd<u32> for HexU32Be {
75    type Output = u32;
76
77    fn bitand(self, rhs: u32) -> Self::Output {
78        self.0 & rhs
79    }
80}
81
82impl<'a> From<B032<'a>> for Extranonce<'a> {
83    fn from(b: B032<'a>) -> Self {
84        Extranonce(b)
85    }
86}
87
88/// Big-endian alternative of the HexU32
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct HexU32Be(pub u32);
91
92impl fmt::Display for HexU32Be {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(f, "{:08x}", self.0)
95    }
96}
97
98impl HexU32Be {
99    pub fn check_mask(&self, mask: &HexU32Be) -> bool {
100        ((!self.0) & mask.0) == 0
101    }
102}
103
104impl From<HexU32Be> for Value {
105    fn from(eu: HexU32Be) -> Self {
106        Into::<String>::into(eu).into()
107    }
108}
109
110impl TryFrom<&str> for HexU32Be {
111    type Error = Error<'static>;
112
113    fn try_from(value: &str) -> Result<Self, Error<'static>> {
114        let expected_len = 8;
115        if value.len() > expected_len {
116            return Err(Error::InvalidHexLen(value.to_string()));
117        }
118
119        let delta_len = expected_len - value.len();
120        let mut prefix = "".to_string();
121        for _ in 0..delta_len {
122            prefix.push('0');
123        }
124        prefix.push_str(value);
125        let parsed_bytes: [u8; 4] = FromHex::from_hex(&prefix)?;
126        Ok(HexU32Be(u32::from_be_bytes(parsed_bytes)))
127    }
128}
129
130/// Helper Serializer
131impl From<HexU32Be> for String {
132    fn from(v: HexU32Be) -> Self {
133        v.0.to_be_bytes().to_hex()
134    }
135}
136
137impl From<u32> for HexU32Be {
138    fn from(a: u32) -> Self {
139        HexU32Be(a)
140    }
141}
142
143//Example of serialization for testing purpose
144impl Serialize for HexU32Be {
145    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
146    where
147        S: serde::Serializer,
148    {
149        let serialized_string = self.0.to_be_bytes().to_hex();
150        serializer.serialize_str(&serialized_string)
151    }
152}
153
154//Example of deserialization for testing purpose
155impl<'de> Deserialize<'de> for HexU32Be {
156    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
157    where
158        D: serde::Deserializer<'de>,
159    {
160        let hex_string: String = Deserialize::deserialize(deserializer)?;
161
162        match u32::from_str_radix(&hex_string, 16) {
163            Ok(value) => Ok(HexU32Be(value)),
164            Err(_) => Err(serde::de::Error::custom("Invalid hex value")),
165        }
166    }
167}
168
169/// PrevHash in Stratum V1 has brain-damaged serialization as it swaps bytes of every u32 word
170/// into big endian. Therefore, we need a special type for it
171#[derive(Clone, Debug, PartialEq, Eq)]
172pub struct PrevHash<'a>(pub U256<'a>);
173
174impl fmt::Display for PrevHash<'_> {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        // Reuse the Stratum V1 serialization logic
177        let s = String::from(self.clone());
178        f.write_str(&s)
179    }
180}
181
182impl<'a> From<PrevHash<'a>> for Vec<u8> {
183    fn from(p_hash: PrevHash<'a>) -> Self {
184        p_hash.0.to_vec()
185    }
186}
187
188impl<'a> TryFrom<&str> for PrevHash<'a> {
189    type Error = Error<'a>;
190
191    fn try_from(value: &str) -> Result<Self, Error<'a>> {
192        // Reorder PrevHash will be stored via this cursor
193        // let mut prev_hash_cursor = std::io::Cursor::new([0_u8; 32]);
194        let mut prev_hash_arr = [0_u8; 32];
195
196        // Decode the plain byte array and sanity check
197        let prev_hash_stratum_order = hex_decode(value)?;
198
199        match prev_hash_stratum_order.len() {
200            32 => {
201                // Swap every u32 from big endian to little endian byte order
202                for (chunk, mut arr_chunks) in prev_hash_stratum_order
203                    .chunks(size_of::<u32>())
204                    .zip(prev_hash_arr.chunks_mut(size_of::<u32>()))
205                {
206                    let prev_hash_word = BigEndian::read_u32(chunk);
207                    arr_chunks
208                        .write_u32::<LittleEndian>(prev_hash_word)
209                        .expect("Internal error: Could not write buffer");
210                }
211                Ok(PrevHash(prev_hash_arr.into()))
212            }
213            _ => Err(error::Error::BadBytesConvert(
214                binary_sv2::Error::InvalidU256(prev_hash_stratum_order.len()),
215            )),
216        }
217    }
218}
219
220impl From<PrevHash<'_>> for Value {
221    fn from(ph: PrevHash) -> Self {
222        Into::<String>::into(ph).into()
223    }
224}
225
226/// Helper Serializer that peforms the reverse process of converting the prev hash into stratum V1
227/// ordering
228impl From<PrevHash<'_>> for String {
229    fn from(v: PrevHash) -> Self {
230        let mut prev_hash_stratum_cursor = std::io::Cursor::new(Vec::new());
231        // swap every u32 from little endian to big endian
232        for chunk in v.0.inner_as_ref().chunks(size_of::<u32>()) {
233            let prev_hash_word = LittleEndian::read_u32(chunk);
234            prev_hash_stratum_cursor
235                .write_u32::<BigEndian>(prev_hash_word)
236                .expect("Internal error: Could not write buffer");
237        }
238        prev_hash_stratum_cursor.into_inner().to_hex()
239    }
240}
241
242// / Referencing the internal part of hex bytes
243impl AsRef<[u8]> for PrevHash<'_> {
244    fn as_ref(&self) -> &[u8] {
245        self.0.inner_as_ref()
246    }
247}
248
249/// Referencing the internal part of hex bytes
250impl<'a> AsRef<U256<'a>> for PrevHash<'a> {
251    fn as_ref(&self) -> &U256<'a> {
252        &self.0
253    }
254}
255
256/// Referencing the internal part of hex bytes
257impl AsRef<[u8]> for Extranonce<'_> {
258    fn as_ref(&self) -> &[u8] {
259        self.0.inner_as_ref()
260    }
261}
262
263#[derive(Clone, Debug, PartialEq, Eq)]
264pub struct MerkleNode<'a>(pub U256<'a>);
265
266impl fmt::Display for MerkleNode<'_> {
267    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268        write!(f, "{}", self.0.inner_as_ref().to_hex())
269    }
270}
271
272impl MerkleNode<'_> {
273    pub fn is_empty(&self) -> bool {
274        self.0.inner_as_ref().is_empty()
275    }
276}
277
278impl<'a> TryFrom<Vec<u8>> for MerkleNode<'a> {
279    type Error = Error<'a>;
280
281    fn try_from(value: Vec<u8>) -> Result<Self, Error<'a>> {
282        let merkle = U256::try_from(value).map_err(error::Error::from)?;
283        Ok(MerkleNode(merkle))
284    }
285}
286
287impl<'a> From<MerkleNode<'a>> for Vec<u8> {
288    fn from(v: MerkleNode<'a>) -> Self {
289        v.0.to_vec()
290    }
291}
292
293impl<'a> From<MerkleNode<'a>> for Value {
294    fn from(eb: MerkleNode<'a>) -> Self {
295        Into::<String>::into(eb).into()
296    }
297}
298
299/// Referencing the internal part of hex bytes
300impl AsRef<[u8]> for MerkleNode<'_> {
301    fn as_ref(&self) -> &[u8] {
302        self.0.inner_as_ref()
303    }
304}
305
306impl<'a> TryFrom<&str> for MerkleNode<'a> {
307    type Error = Error<'a>;
308
309    fn try_from(value: &str) -> Result<Self, Error<'a>> {
310        let merkle = U256::try_from(hex_decode(value)?).map_err(error::Error::from)?;
311        Ok(MerkleNode(merkle))
312    }
313}
314
315impl<'a> From<MerkleNode<'a>> for String {
316    fn from(bytes: MerkleNode<'a>) -> String {
317        bytes.0.inner_as_ref().to_hex()
318    }
319}
320
321/// Helper type that allows simple serialization and deserialization of byte vectors
322/// that are represented as hex strings in JSON.
323/// HexBytes must be less than or equal to 32 bytes.
324#[derive(Clone, Debug, PartialEq, Eq)]
325pub struct HexBytes(Vec<u8>);
326
327impl fmt::Display for HexBytes {
328    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329        write!(f, "{}", self.0.to_hex())
330    }
331}
332
333impl HexBytes {
334    pub fn len(&self) -> usize {
335        self.0.len()
336    }
337    pub fn is_empty(&self) -> bool {
338        self.0.is_empty()
339    }
340}
341
342impl From<Vec<u8>> for HexBytes {
343    fn from(value: Vec<u8>) -> Self {
344        HexBytes(value)
345    }
346}
347
348impl From<HexBytes> for Vec<u8> {
349    fn from(v: HexBytes) -> Self {
350        v.0
351    }
352}
353
354impl From<HexBytes> for Value {
355    fn from(eb: HexBytes) -> Self {
356        Into::<String>::into(eb).into()
357    }
358}
359
360/// Referencing the internal part of hex bytes
361impl AsRef<Vec<u8>> for HexBytes {
362    fn as_ref(&self) -> &Vec<u8> {
363        &self.0
364    }
365}
366
367impl TryFrom<&str> for HexBytes {
368    type Error = Error<'static>;
369
370    fn try_from(value: &str) -> Result<Self, Error<'static>> {
371        Ok(HexBytes(hex_decode(value)?))
372    }
373}
374
375impl From<HexBytes> for String {
376    fn from(bytes: HexBytes) -> String {
377        bytes.0.to_hex()
378    }
379}
380
381//Example of serialization for testing purpose
382impl Serialize for HexBytes {
383    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
384    where
385        S: serde::Serializer,
386    {
387        let bytes = self.0.as_ref();
388        let serialized_string = String::from_utf8_lossy(bytes);
389        serializer.serialize_str(&serialized_string)
390    }
391}
392
393//Example of deserialization for testing purpose
394impl<'de> Deserialize<'de> for HexBytes {
395    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
396    where
397        D: serde::Deserializer<'de>,
398    {
399        let hex_string: String = Deserialize::deserialize(deserializer)?;
400        let bytes = hex_string.as_bytes().to_vec();
401        Ok(HexBytes(bytes))
402    }
403}
404
405#[cfg(test)]
406mod tests {
407    use super::*;
408
409    #[quickcheck_macros::quickcheck]
410    fn test_prev_hash(mut bytes: Vec<u8>) -> bool {
411        bytes.resize(32, 0);
412        let be_hex = bytes.to_hex();
413        let me = PrevHash::try_from(be_hex.clone().as_str()).unwrap();
414        let back_to_hex = String::from(me.clone());
415        let back_to_hex_value = Value::from(me.clone());
416        let value_to_string = back_to_hex_value.as_str().unwrap();
417
418        let chunk_size: usize = size_of::<u32>();
419        let me_chunks = me.clone().0.to_vec();
420        let me_chunks = me_chunks.chunks(chunk_size);
421        for (be_chunk, le_chunk) in bytes.clone().chunks(chunk_size).zip(me_chunks) {
422            let le_chunk = [le_chunk[0], le_chunk[1], le_chunk[2], le_chunk[3]];
423            let be_chunk = [be_chunk[0], be_chunk[1], be_chunk[2], be_chunk[3]];
424            let le_u32 = u32::from_le_bytes(le_chunk);
425            let be_u32 = u32::from_be_bytes(be_chunk);
426
427            if le_u32 != be_u32 {
428                return false;
429            }
430        }
431
432        be_hex == back_to_hex && be_hex == value_to_string
433    }
434
435    #[test]
436    fn merkle_node_try_from_vec_invalid_len_returns_err() {
437        assert!(MerkleNode::try_from(vec![0_u8; 31]).is_err());
438    }
439
440    #[test]
441    fn merkle_node_try_from_str_invalid_len_returns_err() {
442        let invalid_hex = "00".repeat(31);
443        assert!(MerkleNode::try_from(invalid_hex.as_str()).is_err());
444    }
445}