#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate blake2_rfc as blake2;
extern crate byteorder;
extern crate libc;
extern crate serde_json;
use libc::*;
use std::ffi::CString;
use std::ptr::NonNull;
use std::{cmp, fmt, marker};
use blake2::blake2b::Blake2b;
use byteorder::{BigEndian, ByteOrder};
pub const PROOFSIZE: usize = 42;
pub const MAX_NAME_LEN: usize = 256;
pub const MAX_SOLS: usize = 4;
pub type CuckooCreateSolverCtx = unsafe extern "C" fn(*mut SolverParams) -> *mut SolverCtx;
pub type CuckooDestroySolverCtx = unsafe extern "C" fn(*mut SolverCtx);
pub type CuckooRunSolver = unsafe extern "C" fn(
*mut SolverCtx, *const c_uchar, uint32_t, uint64_t, uint32_t, *mut SolverSolutions, *mut SolverStats, ) -> uint32_t;
pub type CuckooStopSolver = unsafe extern "C" fn(*mut SolverCtx);
pub type CuckooFillDefaultParams = unsafe extern "C" fn(*mut SolverParams);
#[derive(Copy, Clone, Debug)]
pub enum SolverCtx {}
pub struct SolverCtxWrapper(pub NonNull<SolverCtx>);
unsafe impl marker::Send for SolverCtxWrapper {}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct SolverParams {
pub nthreads: uint32_t,
pub ntrims: uint32_t,
pub showcycle: bool,
pub allrounds: bool,
pub mutate_nonce: bool,
pub cpuload: bool,
pub device: u32,
pub blocks: u32,
pub tpb: u32,
pub expand: u32,
pub genablocks: u32,
pub genatpb: u32,
pub genbtpb: u32,
pub trimtpb: u32,
pub tailtpb: u32,
pub recoverblocks: u32,
pub recovertpb: u32,
pub platform: u32,
pub edge_bits: u32,
}
impl Default for SolverParams {
fn default() -> SolverParams {
SolverParams {
nthreads: 0,
ntrims: 0,
showcycle: true,
allrounds: false,
mutate_nonce: false,
cpuload: true,
device: 0,
blocks: 0,
tpb: 0,
expand: 0,
genablocks: 0,
genatpb: 0,
genbtpb: 0,
trimtpb: 0,
tailtpb: 0,
recoverblocks: 0,
recovertpb: 0,
platform: 0,
edge_bits: 31,
}
}
}
#[derive(Clone)]
#[repr(C)]
pub struct SolverStats {
pub device_id: uint32_t,
pub edge_bits: uint32_t,
pub plugin_name: [c_uchar; MAX_NAME_LEN],
pub device_name: [c_uchar; MAX_NAME_LEN],
pub has_errored: bool,
pub error_reason: [c_uchar; MAX_NAME_LEN],
pub iterations: uint32_t,
pub last_start_time: uint64_t,
pub last_end_time: uint64_t,
pub last_solution_time: uint64_t,
}
impl Default for SolverStats {
fn default() -> SolverStats {
SolverStats {
device_id: 0,
edge_bits: 0,
plugin_name: [0; MAX_NAME_LEN],
device_name: [0; MAX_NAME_LEN],
has_errored: false,
error_reason: [0; MAX_NAME_LEN],
iterations: 0,
last_start_time: 0,
last_end_time: 0,
last_solution_time: 0,
}
}
}
impl SolverStats {
fn get_name(&self, c_str: &[u8; MAX_NAME_LEN]) -> String {
let v = c_str.clone().to_vec();
let mut i = 0;
for j in 0..v.len() {
if v.get(j) == Some(&0) {
i = j;
break;
}
}
let v = v.split_at(i).0;
match CString::new(v) {
Ok(s) => s.to_str().unwrap().to_owned(),
Err(_) => String::from("Unknown Device Name"),
}
}
pub fn get_device_name(&self) -> String {
self.get_name(&self.device_name)
}
pub fn get_plugin_name(&self) -> String {
self.get_name(&self.plugin_name)
}
pub fn get_error_reason(&self) -> String {
self.get_name(&self.error_reason)
}
pub fn set_plugin_name(&mut self, name: &str) {
let c_vec = CString::new(name).unwrap().into_bytes();
for i in 0..c_vec.len() {
self.plugin_name[i] = c_vec[i];
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Solution {
pub id: uint64_t,
pub nonce: uint64_t,
pub proof: [uint64_t; PROOFSIZE],
}
impl Default for Solution {
fn default() -> Solution {
Solution {
id: 0,
nonce: 0,
proof: [0u64; PROOFSIZE],
}
}
}
impl fmt::Display for Solution {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut comma_separated = String::new();
for num in &self.proof[0..self.proof.len()] {
comma_separated.push_str(&format!("0x{:X}", &num));
comma_separated.push_str(", ");
}
comma_separated.pop();
comma_separated.pop();
write!(f, "Nonce:{} [{}]", self.nonce, comma_separated)
}
}
impl fmt::Debug for Solution {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", &self.proof[..])
}
}
impl cmp::PartialEq for Solution {
fn eq(&self, other: &Solution) -> bool {
for i in 0..PROOFSIZE {
if self.proof[i] != other.proof[i] {
return false;
}
}
return true;
}
}
impl Solution {
pub fn to_u64s(&self) -> Vec<u64> {
let mut nonces = Vec::with_capacity(PROOFSIZE);
for n in self.proof.iter() {
nonces.push(*n as u64);
}
nonces
}
pub fn hash(&self) -> [u8; 32] {
let mut blake2b = Blake2b::new(32);
for n in 0..self.proof.len() {
let mut bytes = [0; 4];
BigEndian::write_u32(&mut bytes, self.proof[n] as u32);
blake2b.update(&bytes);
}
let mut ret = [0; 32];
ret.copy_from_slice(blake2b.finalize().as_bytes());
ret
}
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct SolverSolutions {
pub edge_bits: u32,
pub num_sols: u32,
pub sols: [Solution; MAX_SOLS],
}
impl Default for SolverSolutions {
fn default() -> SolverSolutions {
SolverSolutions {
edge_bits: 0,
num_sols: 0,
sols: [Solution::default(); MAX_SOLS],
}
}
}