1use crate::hexbytes;
6
7use arrayvec::ArrayString;
8use serde::Deserializer;
9use serde_derive::{Deserialize, Serialize};
10
11use std::error::Error;
12use std::fmt::{self, Display, Formatter};
13
14#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
19pub struct WorkerId(ArrayString<[u8; 64]>);
20
21#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
23pub struct JobId(ArrayString<[u8; 64]>);
24
25pub fn deserialize_target<'de, D>(deserializer: D) -> Result<u64, D::Error>
30where
31 D: Deserializer<'de>,
32{
33 let (mut val, hexlen) = hexbytes::hex64le_to_int(deserializer)?;
34 if hexlen <= 8 {
37 val |= val << 0x20;
38 }
39 Ok(val)
40}
41
42#[derive(Debug, Deserialize, Clone)]
44pub struct Job {
45 #[serde(deserialize_with = "hexbytes::hex_to_varbyte")]
46 blob: Vec<u8>,
47 job_id: JobId,
48 #[serde(deserialize_with = "deserialize_target")]
49 target: u64,
50 #[serde(default)]
51 algo: Option<String>,
52 #[serde(default)]
53 variant: u32, }
55
56impl Job {
57 pub fn blob(&self) -> &[u8] {
59 &self.blob
60 }
61
62 pub(crate) fn id(&self) -> JobId {
63 self.job_id
64 }
65
66 pub fn target(&self) -> u64 {
68 self.target
69 }
70
71 pub fn algo(&self) -> Option<&str> {
73 self.algo.as_ref().map(|x| x.as_ref())
74 }
75}
76
77impl PartialEq<Job> for Job {
78 fn eq(&self, other: &Job) -> bool {
79 self.job_id == other.job_id
80 }
81}
82
83#[derive(Debug, Deserialize)]
84#[serde(tag = "method", content = "params", rename_all = "lowercase")]
85pub enum ClientCommand {
86 Job(Job),
87}
88
89#[derive(Debug, Deserialize)]
90pub struct ErrorReply {
91 code: i64,
92 message: String,
93}
94
95impl Display for ErrorReply {
96 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
97 write!(f, "{:?}", &self)
98 }
99}
100
101impl Error for ErrorReply {
102 fn description(&self) -> &str {
103 &self.message
104 }
105}
106
107#[derive(Debug, Deserialize)]
108pub struct JsonMessage<T> {
109 #[serde(default)]
110 pub jsonrpc: Option<String>,
111 #[serde(default)]
112 pub status: Option<String>,
113 #[serde(flatten)]
114 pub body: T,
115}
116
117#[derive(Debug, Deserialize)]
119pub struct JobAssignment {
120 #[serde(rename = "id")]
121 worker_id: WorkerId,
122 job: Job,
123 #[serde(default)]
124 status: Option<String>,
125 #[serde(default)]
126 extensions: Vec<String>,
127}
128
129impl JobAssignment {
130 pub fn worker_id(&self) -> WorkerId {
132 self.worker_id
133 }
134 pub fn into_job(self) -> Job {
136 self.job
137 }
138 pub fn status(&self) -> Option<&str> {
140 self.status.as_ref().map(|x| x.as_ref())
141 }
142 pub fn extensions(&self) -> impl Iterator<Item = &str> {
144 self.extensions.iter().map(|x| x.as_ref())
145 }
146}
147
148#[derive(Debug, Deserialize)]
149#[serde(untagged)]
150pub enum PoolReply {
151 Job(Box<JobAssignment>),
153 Status { status: String },
155}
156
157#[derive(Debug, Deserialize)]
159#[serde(untagged)]
160pub enum PoolEvent<ReqId> {
161 ClientCommand(ClientCommand),
162 PoolReply {
163 id: ReqId,
164 error: Option<ErrorReply>,
165 result: Option<PoolReply>,
166 },
167}
168
169#[derive(Debug, Serialize)]
172pub struct Share {
173 #[serde(rename = "id")]
174 pub worker_id: WorkerId,
175 pub job_id: JobId,
176 #[serde(serialize_with = "hexbytes::u32_to_hex_padded")]
177 pub nonce: u32,
178 #[serde(serialize_with = "hexbytes::byte32_to_hex")]
179 pub result: [u8; 32],
180 pub algo: String,
181}
182
183#[derive(Debug, Serialize)]
184pub struct Credentials {
185 pub login: String,
186 pub pass: String,
187 pub agent: String,
188 pub algo: Vec<String>,
189}
190
191#[derive(Debug, Serialize)]
192#[serde(tag = "method", content = "params", rename_all = "lowercase")]
193pub enum PoolCommand {
194 Submit(Share),
195 Login(Credentials),
196 KeepAlived { id: WorkerId },
197}
198
199#[derive(Debug, Serialize)]
207pub struct PoolRequest<ReqId> {
208 pub id: ReqId,
209 #[serde(flatten)]
210 pub command: PoolCommand,
211}