1#![deny(non_upper_case_globals)]
18#![deny(non_camel_case_types)]
19#![deny(non_snake_case)]
20#![deny(unused_mut)]
21#![warn(missing_docs)]
22
23extern crate serde;
24#[macro_use]
25extern crate serde_derive;
26extern crate blake2_rfc as blake2;
27extern crate byteorder;
28extern crate libc;
29extern crate serde_json;
30
31use libc::*;
32use std::ffi::CString;
33use std::ptr::NonNull;
34use std::{cmp, fmt, marker};
35
36use blake2::blake2b::Blake2b;
37use byteorder::{BigEndian, ByteOrder};
38
39pub const PROOFSIZE: usize = 42;
41pub const MAX_NAME_LEN: usize = 256;
43pub const MAX_SOLS: usize = 4;
45
46pub type CuckooCreateSolverCtx = unsafe extern "C" fn(*mut SolverParams) -> *mut SolverCtx;
49pub type CuckooDestroySolverCtx = unsafe extern "C" fn(*mut SolverCtx);
51pub type CuckooRunSolver = unsafe extern "C" fn(
53 *mut SolverCtx, *const c_uchar, uint32_t, uint64_t, uint32_t, *mut SolverSolutions, *mut SolverStats, ) -> uint32_t;
61pub type CuckooStopSolver = unsafe extern "C" fn(*mut SolverCtx);
63pub type CuckooFillDefaultParams = unsafe extern "C" fn(*mut SolverParams);
65
66#[derive(Copy, Clone, Debug)]
68pub enum SolverCtx {}
69pub struct SolverCtxWrapper(pub NonNull<SolverCtx>);
71unsafe impl marker::Send for SolverCtxWrapper {}
72
73#[derive(Clone, Debug, Serialize, Deserialize)]
75#[repr(C)]
76pub struct SolverParams {
77 pub nthreads: uint32_t,
79 pub ntrims: uint32_t,
81 pub showcycle: bool,
83 pub allrounds: bool,
85 pub mutate_nonce: bool,
88 pub cpuload: bool,
90
91 pub device: u32,
93
94 pub blocks: u32,
96 pub tpb: u32,
98
99 pub expand: u32,
101 pub genablocks: u32,
103 pub genatpb: u32,
105 pub genbtpb: u32,
107 pub trimtpb: u32,
109 pub tailtpb: u32,
111 pub recoverblocks: u32,
113 pub recovertpb: u32,
115 pub platform: u32,
117 pub edge_bits: u32,
119}
120
121impl Default for SolverParams {
122 fn default() -> SolverParams {
123 SolverParams {
124 nthreads: 0,
125 ntrims: 0,
126 showcycle: true,
127 allrounds: false,
128 mutate_nonce: false,
129 cpuload: true,
130 device: 0,
131 blocks: 0,
132 tpb: 0,
133 expand: 0,
134 genablocks: 0,
135 genatpb: 0,
136 genbtpb: 0,
137 trimtpb: 0,
138 tailtpb: 0,
139 recoverblocks: 0,
140 recovertpb: 0,
141 platform: 0,
142 edge_bits: 31,
143 }
144 }
145}
146
147#[derive(Clone)]
149#[repr(C)]
150pub struct SolverStats {
151 pub device_id: uint32_t,
153 pub edge_bits: uint32_t,
155 pub plugin_name: [c_uchar; MAX_NAME_LEN],
157 pub device_name: [c_uchar; MAX_NAME_LEN],
159 pub has_errored: bool,
161 pub error_reason: [c_uchar; MAX_NAME_LEN],
163 pub iterations: uint32_t,
165 pub last_start_time: uint64_t,
167 pub last_end_time: uint64_t,
169 pub last_solution_time: uint64_t,
171}
172
173impl Default for SolverStats {
174 fn default() -> SolverStats {
175 SolverStats {
176 device_id: 0,
177 edge_bits: 0,
178 plugin_name: [0; MAX_NAME_LEN],
179 device_name: [0; MAX_NAME_LEN],
180 has_errored: false,
181 error_reason: [0; MAX_NAME_LEN],
182 iterations: 0,
183 last_start_time: 0,
184 last_end_time: 0,
185 last_solution_time: 0,
186 }
187 }
188}
189
190impl SolverStats {
191 fn get_name(&self, c_str: &[u8; MAX_NAME_LEN]) -> String {
192 let v = c_str.clone().to_vec();
194 let mut i = 0;
195 for j in 0..v.len() {
196 if v.get(j) == Some(&0) {
197 i = j;
198 break;
199 }
200 }
201 let v = v.split_at(i).0;
202 match CString::new(v) {
203 Ok(s) => s.to_str().unwrap().to_owned(),
204 Err(_) => String::from("Unknown Device Name"),
205 }
206 }
207 pub fn get_device_name(&self) -> String {
209 self.get_name(&self.device_name)
210 }
211 pub fn get_plugin_name(&self) -> String {
213 self.get_name(&self.plugin_name)
214 }
215 pub fn get_error_reason(&self) -> String {
217 self.get_name(&self.error_reason)
218 }
219 pub fn set_plugin_name(&mut self, name: &str) {
221 let c_vec = CString::new(name).unwrap().into_bytes();
222 for i in 0..c_vec.len() {
223 self.plugin_name[i] = c_vec[i];
224 }
225 }
226}
227
228#[repr(C)]
230#[derive(Clone, Copy)]
231pub struct Solution {
232 pub id: uint64_t,
234 pub nonce: uint64_t,
236 pub proof: [uint64_t; PROOFSIZE],
238}
239
240impl Default for Solution {
241 fn default() -> Solution {
242 Solution {
243 id: 0,
244 nonce: 0,
245 proof: [0u64; PROOFSIZE],
246 }
247 }
248}
249
250impl fmt::Display for Solution {
251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
252 let mut comma_separated = String::new();
253
254 for num in &self.proof[0..self.proof.len()] {
255 comma_separated.push_str(&format!("0x{:X}", &num));
256 comma_separated.push_str(", ");
257 }
258 comma_separated.pop();
259 comma_separated.pop();
260
261 write!(f, "Nonce:{} [{}]", self.nonce, comma_separated)
262 }
263}
264
265impl fmt::Debug for Solution {
266 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
267 write!(f, "{:?}", &self.proof[..])
268 }
269}
270
271impl cmp::PartialEq for Solution {
272 fn eq(&self, other: &Solution) -> bool {
273 for i in 0..PROOFSIZE {
274 if self.proof[i] != other.proof[i] {
275 return false;
276 }
277 }
278 return true;
279 }
280}
281
282impl Solution {
283 pub fn to_u64s(&self) -> Vec<u64> {
285 let mut nonces = Vec::with_capacity(PROOFSIZE);
286 for n in self.proof.iter() {
287 nonces.push(*n as u64);
288 }
289 nonces
290 }
291
292 pub fn hash(&self) -> [u8; 32] {
296 let mut blake2b = Blake2b::new(32);
298 for n in 0..self.proof.len() {
299 let mut bytes = [0; 4];
300 BigEndian::write_u32(&mut bytes, self.proof[n] as u32);
301 blake2b.update(&bytes);
302 }
303 let mut ret = [0; 32];
304 ret.copy_from_slice(blake2b.finalize().as_bytes());
305 ret
306 }
307}
308
309#[derive(Clone, Copy)]
311#[repr(C)]
312pub struct SolverSolutions {
313 pub edge_bits: u32,
315 pub num_sols: u32,
317 pub sols: [Solution; MAX_SOLS],
319}
320
321impl Default for SolverSolutions {
322 fn default() -> SolverSolutions {
323 SolverSolutions {
324 edge_bits: 0,
325 num_sols: 0,
326 sols: [Solution::default(); MAX_SOLS],
327 }
328 }
329}