Skip to main content

stratum_hns_types/
submit.rs

1use encodings::FromHex;
2use extended_primitives::Buffer;
3use serde::de::{self, SeqAccess, Visitor};
4use serde::{Deserialize, Deserializer};
5use serde_tuple::*;
6use std::fmt;
7use stratum_types::traits::Submit as SubmitTrait;
8
9// #[derive(Clone, Debug, Deserialize, Serialize)]
10#[derive(Serialize_tuple, Clone, Debug, Default)]
11pub struct Submit {
12    pub username: String,
13    pub job_id: String,
14    pub nonce_2: Buffer,
15    pub timestamp: u64,
16    pub nonce: u32,
17    pub mask: Option<Buffer>,
18}
19
20impl SubmitTrait for Submit {
21    fn username(&self) -> String {
22        self.username.clone()
23    }
24}
25
26impl<'de> Deserialize<'de> for Submit {
27    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
28    where
29        D: Deserializer<'de>,
30    {
31        struct SubmitVisitor;
32        use serde::de::Error;
33
34        #[derive(Deserialize)]
35        #[serde(untagged)]
36        enum StringOrInt {
37            String(String),
38            Int(u64),
39        }
40
41        // match StringOrInt::deserialize(deserializer)? {
42        //     StringOrInt::String(s) => s.parse().map_err(de::Error::custom),
43        //     StringOrInt::Int(i) => Ok(i),
44        // }
45
46        impl<'de> Visitor<'de> for SubmitVisitor {
47            type Value = Submit;
48
49            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50                formatter.write_str("struct Submit")
51            }
52
53            fn visit_seq<V>(self, mut seq: V) -> Result<Submit, V::Error>
54            where
55                V: SeqAccess<'de>,
56            {
57                let username = seq
58                    .next_element()?
59                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
60                let job_id = seq
61                    .next_element()?
62                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
63                let nonce_2 = seq
64                    .next_element()?
65                    .ok_or_else(|| de::Error::invalid_length(2, &self))?;
66                let timestamp: StringOrInt = seq
67                    .next_element()?
68                    .ok_or_else(|| de::Error::invalid_length(3, &self))?;
69                let nonce: StringOrInt = seq
70                    .next_element()?
71                    .ok_or_else(|| de::Error::invalid_length(4, &self))?;
72
73                let mask = seq.next_element()?;
74
75                if mask.is_some() {
76                    let real_timestamp = match timestamp {
77                        StringOrInt::String(hex) => {
78                            let bytes = Vec::from_hex(hex).map_err(Error::custom)?;
79
80                            if bytes.len() == 4 {
81                                let mut byte_array = [0u8; 4];
82                                byte_array.copy_from_slice(&bytes);
83
84                                u32::from_be_bytes(byte_array) as u64
85                            } else if bytes.len() == 8 {
86                                let mut byte_array = [0u8; 8];
87                                byte_array.copy_from_slice(&bytes);
88
89                                u64::from_be_bytes(byte_array) as u64
90                            } else {
91                                return Err(Error::custom("Timestamp out of range"));
92                            }
93                        }
94                        StringOrInt::Int(raw) => raw,
95                    };
96
97                    let real_nonce = match nonce {
98                        StringOrInt::String(hex) => {
99                            let bytes = Vec::from_hex(hex).map_err(Error::custom)?;
100
101                            if bytes.len() == 4 {
102                                let mut byte_array = [0u8; 4];
103                                byte_array.copy_from_slice(&bytes);
104
105                                u32::from_be_bytes(byte_array)
106                            } else if bytes.len() == 8 {
107                                let mut byte_array = [0u8; 8];
108                                byte_array.copy_from_slice(&bytes);
109
110                                let nonce = u64::from_be_bytes(byte_array);
111
112                                if nonce <= u32::max_value() as u64 {
113                                    nonce as u32
114                                } else {
115                                    return Err(Error::custom("Nonce out of range"));
116                                }
117                            } else {
118                                return Err(Error::custom("Nonce out of range"));
119                            }
120                        }
121                        StringOrInt::Int(raw) => raw as u32,
122                    };
123
124                    Ok(Submit {
125                        username,
126                        job_id,
127                        nonce_2,
128                        timestamp: real_timestamp,
129                        nonce: real_nonce,
130                        mask,
131                    })
132                } else {
133                    let real_timestamp = match timestamp {
134                        StringOrInt::String(raw_time) => raw_time.parse().map_err(Error::custom)?,
135                        StringOrInt::Int(raw) => raw,
136                    };
137
138                    let real_nonce = match nonce {
139                        StringOrInt::String(raw_nonce) => {
140                            raw_nonce.parse().map_err(Error::custom)?
141                        }
142                        StringOrInt::Int(raw) => raw as u32,
143                    };
144
145                    Ok(Submit {
146                        username,
147                        job_id,
148                        nonce_2,
149                        timestamp: real_timestamp,
150                        nonce: real_nonce,
151                        mask,
152                    })
153                }
154            }
155        }
156
157        deserializer.deserialize_seq(SubmitVisitor)
158    }
159}