diff --git a/core/src/global.rs b/core/src/global.rs index b659eff76a..5578650021 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -25,7 +25,7 @@ use crate::consensus::{ use crate::core::block::HeaderVersion; use crate::pow::{ self, new_cuckaroo_ctx, new_cuckarood_ctx, new_cuckaroom_ctx, new_cuckarooz_ctx, - new_cuckatoo_ctx, EdgeType, PoWContext, + new_cuckatoo_ctx, PoWContext, }; use std::cell::Cell; use util::OneTime; @@ -219,10 +219,7 @@ pub fn create_pow_context( edge_bits: u8, proof_size: usize, max_sols: u32, -) -> Result>, pow::Error> -where - T: EdgeType + 'static, -{ +) -> Result, pow::Error> { let chain_type = get_chain_type(); match chain_type { // Mainnet has Cuckaroo{,d,m,z}29 for AR and Cuckatoo31+ for AF diff --git a/core/src/pow/common.rs b/core/src/pow/common.rs index e860280708..a12139dafb 100644 --- a/core/src/pow/common.rs +++ b/core/src/pow/common.rs @@ -14,7 +14,7 @@ //! Common types and traits for cuckoo family of solvers -use crate::pow::error::{Error, ErrorKind}; +use crate::pow::error::Error; use crate::pow::num::{PrimInt, ToPrimitive}; use crate::pow::siphash::siphash24; use blake2::blake2b::blake2b; @@ -31,49 +31,27 @@ impl EdgeType for u64 {} /// An edge in the Cuckoo graph, simply references two u64 nodes. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] -pub struct Edge -where - T: EdgeType, -{ - pub u: T, - pub v: T, +pub struct Edge { + pub u: u64, + pub v: u64, } -impl fmt::Display for Edge -where - T: EdgeType, -{ +impl fmt::Display for Edge { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(u: {}, v: {})", - self.u.to_u64().unwrap_or(0), - self.v.to_u64().unwrap_or(0) - ) + write!(f, "(u: {}, v: {})", self.u, self.v) } } /// An element of an adjencency list #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Link -where - T: EdgeType, -{ - pub next: T, - pub to: T, +pub struct Link { + pub next: u64, + pub to: u64, } -impl fmt::Display for Link -where - T: EdgeType, -{ +impl fmt::Display for Link { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "(next: {}, to: {})", - self.next.to_u64().unwrap_or(0), - self.to.to_u64().unwrap_or(0) - ) + write!(f, "(next: {}, to: {})", self.next, self.to) } } @@ -135,31 +113,29 @@ macro_rules! to_edge { /// Utility struct to calculate commonly used Cuckoo parameters calculated /// from header, nonce, edge_bits, etc. -pub struct CuckooParams -where - T: EdgeType, -{ +pub struct CuckooParams { pub edge_bits: u8, pub proof_size: usize, pub num_edges: u64, pub siphash_keys: [u64; 4], - pub edge_mask: T, + pub edge_mask: u64, + pub node_mask: u64, } -impl CuckooParams -where - T: EdgeType, -{ +impl CuckooParams { /// Instantiates new params and calculate edge mask, etc - pub fn new(edge_bits: u8, proof_size: usize) -> Result, Error> { - let num_edges = (1 as u64) << edge_bits; - let edge_mask = to_edge!(T, num_edges - 1); + pub fn new(edge_bits: u8, node_bits: u8, proof_size: usize) -> Result { + let num_edges = 1u64 << edge_bits; + let edge_mask = num_edges - 1; + let num_nodes = 1u64 << node_bits; + let node_mask = num_nodes - 1; Ok(CuckooParams { edge_bits, proof_size, num_edges, siphash_keys: [0; 4], edge_mask, + node_mask, }) } @@ -170,16 +146,9 @@ where } /// Return siphash masked for type - pub fn sipnode(&self, edge: T, uorv: u64, shift: bool) -> Result { - let hash_u64 = siphash24( - &self.siphash_keys, - 2 * edge.to_u64().ok_or(ErrorKind::IntegerCast)? + uorv, - ); - let mut masked = hash_u64 & self.edge_mask.to_u64().ok_or(ErrorKind::IntegerCast)?; - if shift { - masked <<= 1; - masked |= uorv; - } - Ok(T::from(masked).ok_or(ErrorKind::IntegerCast)?) + pub fn sipnode(&self, edge: u64, uorv: u64) -> Result { + let hash_u64 = siphash24(&self.siphash_keys, 2 * edge + uorv); + let node = hash_u64 & self.node_mask; + Ok(node) } } diff --git a/core/src/pow/cuckaroo.rs b/core/src/pow/cuckaroo.rs index 2f4f62fc7b..61447f861f 100644 --- a/core/src/pow/cuckaroo.rs +++ b/core/src/pow/cuckaroo.rs @@ -24,7 +24,7 @@ //! obtain blocks of values. Nodes are then extracted from those edges. use crate::global; -use crate::pow::common::{CuckooParams, EdgeType}; +use crate::pow::common::CuckooParams; use crate::pow::error::{Error, ErrorKind}; use crate::pow::siphash::siphash_block; use crate::pow::{PoWContext, Proof}; @@ -32,29 +32,17 @@ use crate::pow::{PoWContext, Proof}; /// Instantiate a new CuckarooContext as a PowContext. Note that this can't /// be moved in the PoWContext trait as this particular trait needs to be /// convertible to an object trait. -pub fn new_cuckaroo_ctx( - edge_bits: u8, - proof_size: usize, -) -> Result>, Error> -where - T: EdgeType + 'static, -{ - let params = CuckooParams::new(edge_bits, proof_size)?; +pub fn new_cuckaroo_ctx(edge_bits: u8, proof_size: usize) -> Result, Error> { + let params = CuckooParams::new(edge_bits, edge_bits, proof_size)?; Ok(Box::new(CuckarooContext { params })) } /// Cuckaroo cycle context. Only includes the verifier for now. -pub struct CuckarooContext -where - T: EdgeType, -{ - params: CuckooParams, +pub struct CuckarooContext { + params: CuckooParams, } -impl PoWContext for CuckarooContext -where - T: EdgeType, -{ +impl PoWContext for CuckarooContext { fn set_header_nonce( &mut self, header: Vec, @@ -76,10 +64,9 @@ where let mut uvs = vec![0u64; 2 * proof.proof_size()]; let mut xor0: u64 = 0; let mut xor1: u64 = 0; - let node_mask: u64 = to_u64!(self.params.edge_mask); for n in 0..proof.proof_size() { - if nonces[n] > to_u64!(self.params.edge_mask) { + if nonces[n] > self.params.edge_mask { return Err(ErrorKind::Verification("edge too big".to_owned()).into()); } if n > 0 && nonces[n] <= nonces[n - 1] { @@ -87,9 +74,9 @@ where } // 21 is standard siphash rotation constant let edge: u64 = siphash_block(&self.params.siphash_keys, nonces[n], 21, false); - uvs[2 * n] = edge & node_mask; + uvs[2 * n] = edge & self.params.node_mask; xor0 ^= uvs[2 * n]; - uvs[2 * n + 1] = (edge >> 32) & node_mask; + uvs[2 * n + 1] = (edge >> 32) & self.params.node_mask; xor1 ^= uvs[2 * n + 1]; } if xor0 | xor1 != 0 { @@ -169,7 +156,7 @@ mod test { #[test] fn cuckaroo19_vectors() { global::set_local_chain_type(global::ChainTypes::Mainnet); - let mut ctx = new_impl::(19, 42); + let mut ctx = new_impl(19, 42); ctx.params.siphash_keys = V1_19_HASH; assert!(ctx.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok()); ctx.params.siphash_keys = V2_19_HASH.clone(); @@ -177,11 +164,8 @@ mod test { assert!(ctx.verify(&Proof::zero(42)).is_err()); } - fn new_impl(edge_bits: u8, proof_size: usize) -> CuckarooContext - where - T: EdgeType, - { - let params = CuckooParams::new(edge_bits, proof_size).unwrap(); + fn new_impl(edge_bits: u8, proof_size: usize) -> CuckarooContext { + let params = CuckooParams::new(edge_bits, edge_bits, proof_size).unwrap(); CuckarooContext { params } } } diff --git a/core/src/pow/cuckarood.rs b/core/src/pow/cuckarood.rs index a4e1e00dc3..61fd7e5e28 100644 --- a/core/src/pow/cuckarood.rs +++ b/core/src/pow/cuckarood.rs @@ -23,7 +23,7 @@ //! and requires cycles to alternate between even- and odd-indexed edges. use crate::global; -use crate::pow::common::{CuckooParams, EdgeType}; +use crate::pow::common::CuckooParams; use crate::pow::error::{Error, ErrorKind}; use crate::pow::siphash::siphash_block; use crate::pow::{PoWContext, Proof}; @@ -31,29 +31,17 @@ use crate::pow::{PoWContext, Proof}; /// Instantiate a new CuckaroodContext as a PowContext. Note that this can't /// be moved in the PoWContext trait as this particular trait needs to be /// convertible to an object trait. -pub fn new_cuckarood_ctx( - edge_bits: u8, - proof_size: usize, -) -> Result>, Error> -where - T: EdgeType + 'static, -{ - let params = CuckooParams::new(edge_bits, proof_size)?; +pub fn new_cuckarood_ctx(edge_bits: u8, proof_size: usize) -> Result, Error> { + let params = CuckooParams::new(edge_bits, edge_bits - 1, proof_size)?; Ok(Box::new(CuckaroodContext { params })) } /// Cuckarood cycle context. Only includes the verifier for now. -pub struct CuckaroodContext -where - T: EdgeType, -{ - params: CuckooParams, +pub struct CuckaroodContext { + params: CuckooParams, } -impl PoWContext for CuckaroodContext -where - T: EdgeType, -{ +impl PoWContext for CuckaroodContext { fn set_header_nonce( &mut self, header: Vec, @@ -76,14 +64,13 @@ where let mut ndir = vec![0usize; 2]; let mut xor0: u64 = 0; let mut xor1: u64 = 0; - let node_mask: u64 = to_u64!(self.params.edge_mask) >> 1; for n in 0..proof.proof_size() { let dir = (nonces[n] & 1) as usize; if ndir[dir] >= proof.proof_size() / 2 { return Err(ErrorKind::Verification("edges not balanced".to_owned()).into()); } - if nonces[n] > to_u64!(self.params.edge_mask) { + if nonces[n] > self.params.edge_mask { return Err(ErrorKind::Verification("edge too big".to_owned()).into()); } if n > 0 && nonces[n] <= nonces[n - 1] { @@ -92,9 +79,9 @@ where // cuckarood uses a non-standard siphash rotation constant 25 as anti-ASIC tweak let edge: u64 = siphash_block(&self.params.siphash_keys, nonces[n], 25, false); let idx = 4 * ndir[dir] + 2 * dir; - uvs[idx] = edge & node_mask; + uvs[idx] = edge & self.params.node_mask; xor0 ^= uvs[idx]; - uvs[idx + 1] = (edge >> 32) & node_mask; + uvs[idx + 1] = (edge >> 32) & self.params.node_mask; xor1 ^= uvs[idx + 1]; ndir[dir] += 1; } @@ -171,21 +158,18 @@ mod test { #[test] fn cuckarood19_29_vectors() { global::set_local_chain_type(global::ChainTypes::Mainnet); - let mut ctx19 = new_impl::(19, 42); + let mut ctx19 = new_impl(19, 42); ctx19.params.siphash_keys = V1_19_HASH; assert!(ctx19.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok()); assert!(ctx19.verify(&Proof::zero(42)).is_err()); - let mut ctx29 = new_impl::(29, 42); + let mut ctx29 = new_impl(29, 42); ctx29.params.siphash_keys = V2_29_HASH; assert!(ctx29.verify(&Proof::new(V2_29_SOL.to_vec())).is_ok()); assert!(ctx29.verify(&Proof::zero(42)).is_err()); } - fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroodContext - where - T: EdgeType, - { - let params = CuckooParams::new(edge_bits, proof_size).unwrap(); + fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroodContext { + let params = CuckooParams::new(edge_bits, edge_bits - 1, proof_size).unwrap(); CuckaroodContext { params } } } diff --git a/core/src/pow/cuckaroom.rs b/core/src/pow/cuckaroom.rs index 82f9f36bb7..dd0aa8ae58 100644 --- a/core/src/pow/cuckaroom.rs +++ b/core/src/pow/cuckaroom.rs @@ -22,7 +22,7 @@ //! in a mono-partite graph, from which it derives the letter 'm'. use crate::global; -use crate::pow::common::{CuckooParams, EdgeType}; +use crate::pow::common::CuckooParams; use crate::pow::error::{Error, ErrorKind}; use crate::pow::siphash::siphash_block; use crate::pow::{PoWContext, Proof}; @@ -30,29 +30,17 @@ use crate::pow::{PoWContext, Proof}; /// Instantiate a new CuckaroomContext as a PowContext. Note that this can't /// be moved in the PoWContext trait as this particular trait needs to be /// convertible to an object trait. -pub fn new_cuckaroom_ctx( - edge_bits: u8, - proof_size: usize, -) -> Result>, Error> -where - T: EdgeType + 'static, -{ - let params = CuckooParams::new(edge_bits, proof_size)?; +pub fn new_cuckaroom_ctx(edge_bits: u8, proof_size: usize) -> Result, Error> { + let params = CuckooParams::new(edge_bits, edge_bits, proof_size)?; Ok(Box::new(CuckaroomContext { params })) } /// Cuckaroom cycle context. Only includes the verifier for now. -pub struct CuckaroomContext -where - T: EdgeType, -{ - params: CuckooParams, +pub struct CuckaroomContext { + params: CuckooParams, } -impl PoWContext for CuckaroomContext -where - T: EdgeType, -{ +impl PoWContext for CuckaroomContext { fn set_header_nonce( &mut self, header: Vec, @@ -76,10 +64,9 @@ where let mut to = vec![0u64; proofsize]; let mut xor_from: u64 = 0; let mut xor_to: u64 = 0; - let node_mask: u64 = to_u64!(self.params.edge_mask) >> 1; for n in 0..proofsize { - if nonces[n] > to_u64!(self.params.edge_mask) { + if nonces[n] > self.params.edge_mask { return Err(ErrorKind::Verification("edge too big".to_owned()).into()); } if n > 0 && nonces[n] <= nonces[n - 1] { @@ -87,9 +74,9 @@ where } // 21 is standard siphash rotation constant let edge: u64 = siphash_block(&self.params.siphash_keys, nonces[n], 21, true); - from[n] = edge & node_mask; + from[n] = edge & self.params.node_mask; xor_from ^= from[n]; - to[n] = (edge >> 32) & node_mask; + to[n] = (edge >> 32) & self.params.node_mask; xor_to ^= to[n]; } if xor_from != xor_to { @@ -164,21 +151,18 @@ mod test { #[test] fn cuckaroom19_29_vectors() { global::set_local_chain_type(global::ChainTypes::Mainnet); - let mut ctx19 = new_impl::(19, 42); + let mut ctx19 = new_impl(19, 42); ctx19.params.siphash_keys = V1_19_HASH; assert!(ctx19.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok()); assert!(ctx19.verify(&Proof::zero(42)).is_err()); - let mut ctx29 = new_impl::(29, 42); + let mut ctx29 = new_impl(29, 42); ctx29.params.siphash_keys = V2_29_HASH; assert!(ctx29.verify(&Proof::new(V2_29_SOL.to_vec())).is_ok()); assert!(ctx29.verify(&Proof::zero(42)).is_err()); } - fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroomContext - where - T: EdgeType, - { - let params = CuckooParams::new(edge_bits, proof_size).unwrap(); + fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroomContext { + let params = CuckooParams::new(edge_bits, edge_bits, proof_size).unwrap(); CuckaroomContext { params } } } diff --git a/core/src/pow/cuckarooz.rs b/core/src/pow/cuckarooz.rs index 74d73e0c15..730140b347 100644 --- a/core/src/pow/cuckarooz.rs +++ b/core/src/pow/cuckarooz.rs @@ -23,7 +23,7 @@ //! accordingly. use crate::global; -use crate::pow::common::{CuckooParams, EdgeType}; +use crate::pow::common::CuckooParams; use crate::pow::error::{Error, ErrorKind}; use crate::pow::siphash::siphash_block; use crate::pow::{PoWContext, Proof}; @@ -31,29 +31,17 @@ use crate::pow::{PoWContext, Proof}; /// Instantiate a new CuckaroozContext as a PowContext. Note that this can't /// be moved in the PoWContext trait as this particular trait needs to be /// convertible to an object trait. -pub fn new_cuckarooz_ctx( - edge_bits: u8, - proof_size: usize, -) -> Result>, Error> -where - T: EdgeType + 'static, -{ - let params = CuckooParams::new(edge_bits, proof_size)?; +pub fn new_cuckarooz_ctx(edge_bits: u8, proof_size: usize) -> Result, Error> { + let params = CuckooParams::new(edge_bits, edge_bits + 1, proof_size)?; Ok(Box::new(CuckaroozContext { params })) } /// Cuckarooz cycle context. Only includes the verifier for now. -pub struct CuckaroozContext -where - T: EdgeType, -{ - params: CuckooParams, +pub struct CuckaroozContext { + params: CuckooParams, } -impl PoWContext for CuckaroozContext -where - T: EdgeType, -{ +impl PoWContext for CuckaroozContext { fn set_header_nonce( &mut self, header: Vec, @@ -74,10 +62,9 @@ where let nonces = &proof.nonces; let mut uvs = vec![0u64; 2 * proof.proof_size()]; let mut xoruv: u64 = 0; - let node_mask: u64 = to_u64!(self.params.edge_mask) << 1 | 1; for n in 0..proof.proof_size() { - if nonces[n] > to_u64!(self.params.edge_mask) { + if nonces[n] > self.params.edge_mask { return Err(ErrorKind::Verification("edge too big".to_owned()).into()); } if n > 0 && nonces[n] <= nonces[n - 1] { @@ -85,8 +72,8 @@ where } // 21 is standard siphash rotation constant let edge: u64 = siphash_block(&self.params.siphash_keys, nonces[n], 21, true); - uvs[2 * n] = edge & node_mask; - uvs[2 * n + 1] = (edge >> 32) & node_mask; + uvs[2 * n] = edge & self.params.node_mask; + uvs[2 * n + 1] = (edge >> 32) & self.params.node_mask; xoruv ^= uvs[2 * n] ^ uvs[2 * n + 1]; } if xoruv != 0 { @@ -167,13 +154,13 @@ mod test { #[test] fn cuckarooz19_29_vectors() { global::set_local_chain_type(global::ChainTypes::Mainnet); - let mut ctx19 = new_impl::(19, 42); + let mut ctx19 = new_impl(19, 42); ctx19.params.siphash_keys = V1_19_HASH.clone(); assert!(ctx19 .verify(&Proof::new(V1_19_SOL.to_vec().clone())) .is_ok()); assert!(ctx19.verify(&Proof::zero(42)).is_err()); - let mut ctx29 = new_impl::(29, 42); + let mut ctx29 = new_impl(29, 42); ctx29.params.siphash_keys = V2_29_HASH.clone(); assert!(ctx29 .verify(&Proof::new(V2_29_SOL.to_vec().clone())) @@ -181,11 +168,8 @@ mod test { assert!(ctx29.verify(&Proof::zero(42)).is_err()); } - fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroozContext - where - T: EdgeType, - { - let params = CuckooParams::new(edge_bits, proof_size).unwrap(); + fn new_impl(edge_bits: u8, proof_size: usize) -> CuckaroozContext { + let params = CuckooParams::new(edge_bits, edge_bits + 1, proof_size).unwrap(); CuckaroozContext { params } } } diff --git a/core/src/pow/cuckatoo.rs b/core/src/pow/cuckatoo.rs index d4106ff78e..508b2612c0 100644 --- a/core/src/pow/cuckatoo.rs +++ b/core/src/pow/cuckatoo.rs @@ -13,7 +13,7 @@ //! Implementation of Cuckatoo Cycle designed by John Tromp. use crate::global; -use crate::pow::common::{CuckooParams, EdgeType, Link}; +use crate::pow::common::{CuckooParams, Link}; use crate::pow::error::{Error, ErrorKind}; use crate::pow::{PoWContext, Proof}; use byteorder::{BigEndian, WriteBytesExt}; @@ -21,18 +21,15 @@ use croaring::Bitmap; use std::mem; use util::ToHex; -struct Graph -where - T: EdgeType, -{ +struct Graph { /// Maximum number of edges - max_edges: T, + max_edges: u64, /// Maximum nodes max_nodes: u64, /// Adjacency links - links: Vec>, + links: Vec, /// Index into links array - adj_list: Vec, + adj_list: Vec, /// visited: Bitmap, /// Maximum solutions @@ -42,19 +39,16 @@ where /// proof size proof_size: usize, /// define NIL type - nil: T, + nil: u64, } -impl Graph -where - T: EdgeType, -{ +impl Graph { /// Create a new graph with given parameters - pub fn new(max_edges: T, max_sols: u32, proof_size: usize) -> Result, Error> { - if to_u64!(max_edges) >= u64::max_value() / 2 { + pub fn new(max_edges: u64, max_sols: u32, proof_size: usize) -> Result { + if max_edges >= u64::max_value() / 2 { return Err(ErrorKind::Verification("graph is to big to build".to_string()).into()); } - let max_nodes = 2 * to_u64!(max_edges); + let max_nodes = 2 * max_edges; Ok(Graph { max_edges, max_nodes, @@ -64,55 +58,52 @@ where adj_list: vec![], visited: Bitmap::create(), solutions: vec![], - nil: T::max_value(), + nil: u64::max_value(), }) } pub fn reset(&mut self) -> Result<(), Error> { //TODO: Can be optimised self.links = Vec::with_capacity(2 * self.max_nodes as usize); - self.adj_list = vec![T::max_value(); 2 * self.max_nodes as usize]; + self.adj_list = vec![u64::max_value(); 2 * self.max_nodes as usize]; self.solutions = vec![Proof::zero(self.proof_size); 1]; self.visited = Bitmap::create(); Ok(()) } pub fn byte_count(&self) -> Result { - Ok( - 2 * to_u64!(self.max_edges) * mem::size_of::>() as u64 - + mem::size_of::() as u64 * 2 * self.max_nodes, - ) + Ok(2 * self.max_edges * mem::size_of::() as u64 + + mem::size_of::() as u64 * 2 * self.max_nodes) } /// Add an edge to the graph - pub fn add_edge(&mut self, u: T, mut v: T) -> Result<(), Error> { - let max_nodes_t = to_edge!(T, self.max_nodes); - if u >= max_nodes_t || v >= max_nodes_t { + pub fn add_edge(&mut self, u: u64, mut v: u64) -> Result<(), Error> { + if u >= self.max_nodes || v >= self.max_nodes { return Err(ErrorKind::EdgeAddition.into()); } - v = v + to_edge!(T, self.max_nodes); - let adj_u = self.adj_list[to_usize!(u ^ T::one())]; - let adj_v = self.adj_list[to_usize!(v ^ T::one())]; + v = v + self.max_nodes; + let adj_u = self.adj_list[(u ^ 1) as usize]; + let adj_v = self.adj_list[(v ^ 1) as usize]; if adj_u != self.nil && adj_v != self.nil { let sol_index = self.solutions.len() - 1; self.solutions[sol_index].nonces[0] = self.links.len() as u64 / 2; self.cycles_with_link(1, u, v)?; } - let ulink = self.links.len(); - let vlink = self.links.len() + 1; - if to_edge!(T, vlink) == self.nil { + let ulink = self.links.len() as u64; + let vlink = (self.links.len() + 1) as u64; + if vlink == self.nil { return Err(ErrorKind::EdgeAddition.into()); } self.links.push(Link { - next: self.adj_list[to_usize!(u)], + next: self.adj_list[u as usize], to: u, }); self.links.push(Link { - next: self.adj_list[to_usize!(v)], + next: self.adj_list[v as usize], to: v, }); - self.adj_list[to_usize!(u)] = T::from(ulink).ok_or(ErrorKind::IntegerCast)?; - self.adj_list[to_usize!(v)] = T::from(vlink).ok_or(ErrorKind::IntegerCast)?; + self.adj_list[u as usize] = ulink; + self.adj_list[v as usize] = vlink; Ok(()) } @@ -120,11 +111,11 @@ where self.visited.contains(u as u32) } - fn cycles_with_link(&mut self, len: u32, u: T, dest: T) -> Result<(), Error> { - if self.test_bit(to_u64!(u >> 1)) { + fn cycles_with_link(&mut self, len: u32, u: u64, dest: u64) -> Result<(), Error> { + if self.test_bit(u >> 1) { return Ok(()); } - if (u ^ T::one()) == dest { + if (u ^ 1) == dest { if len == self.proof_size as u32 { if self.solutions.len() < self.max_sols as usize { // create next solution @@ -135,20 +126,20 @@ where } else if len == self.proof_size as u32 { return Ok(()); } - let mut au1 = self.adj_list[to_usize!(u ^ T::one())]; + let mut au1 = self.adj_list[(u ^ 1) as usize]; if au1 != self.nil { - self.visited.add(to_u32!(u >> 1)); + self.visited.add((u >> 1) as u32); while au1 != self.nil { let i = self.solutions.len() - 1; - self.solutions[i].nonces[len as usize] = to_u64!(au1) / 2; - let link_index = to_usize!(au1 ^ T::one()); + self.solutions[i].nonces[len as usize] = au1 / 2; + let link_index = (au1 ^ 1) as usize; let link = self.links[link_index].to; if link != self.nil { self.cycles_with_link(len + 1, link, dest)?; } - au1 = self.links[to_usize!(au1)].next; + au1 = self.links[au1 as usize].next; } - self.visited.remove(to_u32!(u >> 1)); + self.visited.remove((u >> 1) as u32); } Ok(()) } @@ -157,32 +148,23 @@ where /// Instantiate a new CuckatooContext as a PowContext. Note that this can't /// be moved in the PoWContext trait as this particular trait needs to be /// convertible to an object trait. -pub fn new_cuckatoo_ctx( +pub fn new_cuckatoo_ctx( edge_bits: u8, proof_size: usize, max_sols: u32, -) -> Result>, Error> -where - T: EdgeType + 'static, -{ - Ok(Box::new(CuckatooContext::::new_impl( +) -> Result, Error> { + Ok(Box::new(CuckatooContext::new_impl( edge_bits, proof_size, max_sols, )?)) } /// Cuckatoo solver context -pub struct CuckatooContext -where - T: EdgeType, -{ - params: CuckooParams, - graph: Graph, +pub struct CuckatooContext { + params: CuckooParams, + graph: Graph, } -impl PoWContext for CuckatooContext -where - T: EdgeType, -{ +impl PoWContext for CuckatooContext { fn set_header_nonce( &mut self, header: Vec, @@ -202,18 +184,15 @@ where } } -impl CuckatooContext -where - T: EdgeType, -{ +impl CuckatooContext { /// New Solver context pub fn new_impl( edge_bits: u8, proof_size: usize, max_sols: u32, - ) -> Result, Error> { - let params = CuckooParams::new(edge_bits, proof_size)?; - let num_edges = to_edge!(T, params.num_edges); + ) -> Result { + let params = CuckooParams::new(edge_bits, edge_bits, proof_size)?; + let num_edges = params.num_edges; Ok(CuckatooContext { params, graph: Graph::new(num_edges, max_sols, proof_size)?, @@ -246,11 +225,6 @@ where Ok(()) } - /// Return siphash masked for type - pub fn sipnode(&self, edge: T, uorv: u64) -> Result { - self.params.sipnode(edge, uorv, false) - } - /// Simple implementation of algorithm pub fn find_cycles_iter(&mut self, iter: I) -> Result, Error> where @@ -259,9 +233,9 @@ where let mut val = vec![]; for n in iter { val.push(n); - let u = self.sipnode(to_edge!(T, n), 0)?; - let v = self.sipnode(to_edge!(T, n), 1)?; - self.graph.add_edge(to_edge!(T, u), to_edge!(T, v))?; + let u = self.params.sipnode(n, 0)?; + let v = self.params.sipnode(n, 1)?; + self.graph.add_edge(u, v)?; } self.graph.solutions.pop(); for s in &mut self.graph.solutions { @@ -290,14 +264,14 @@ where let mut xor1: u64 = xor0; for n in 0..proof.proof_size() { - if nonces[n] > to_u64!(self.params.edge_mask) { + if nonces[n] > self.params.edge_mask { return Err(ErrorKind::Verification("edge too big".to_owned()).into()); } if n > 0 && nonces[n] <= nonces[n - 1] { return Err(ErrorKind::Verification("edges not ascending".to_owned()).into()); } - uvs[2 * n] = to_u64!(self.sipnode(to_edge!(T, nonces[n]), 0)?); - uvs[2 * n + 1] = to_u64!(self.sipnode(to_edge!(T, nonces[n]), 1)?); + uvs[2 * n] = self.params.sipnode(nonces[n], 0)?; + uvs[2 * n + 1] = self.params.sipnode(nonces[n], 1)?; xor0 ^= uvs[2 * n]; xor1 ^= uvs[2 * n + 1]; } @@ -368,65 +342,56 @@ mod test { #[test] fn cuckatoo() { global::set_local_chain_type(global::ChainTypes::Mainnet); - let ret = basic_solve::(); + let ret = basic_solve(); if let Err(r) = ret { panic!("basic_solve u32: Error: {}", r); } - let ret = basic_solve::(); + let ret = basic_solve(); if let Err(r) = ret { panic!("basic_solve u64: Error: {}", r); } - let ret = validate29_vectors::(); + let ret = validate29_vectors(); if let Err(r) = ret { panic!("validate_29_vectors u32: Error: {}", r); } - let ret = validate29_vectors::(); + let ret = validate29_vectors(); if let Err(r) = ret { panic!("validate_29_vectors u64: Error: {}", r); } - let ret = validate31_vectors::(); + let ret = validate31_vectors(); if let Err(r) = ret { panic!("validate_31_vectors u32: Error: {}", r); } - let ret = validate31_vectors::(); + let ret = validate31_vectors(); if let Err(r) = ret { panic!("validate_31_vectors u64: Error: {}", r); } - let ret = validate_fail::(); + let ret = validate_fail(); if let Err(r) = ret { panic!("validate_fail u32: Error: {}", r); } - let ret = validate_fail::(); + let ret = validate_fail(); if let Err(r) = ret { panic!("validate_fail u64: Error: {}", r); } } - fn validate29_vectors() -> Result<(), Error> - where - T: EdgeType, - { - let mut ctx = CuckatooContext::::new_impl(29, 42, 10).unwrap(); + fn validate29_vectors() -> Result<(), Error> { + let mut ctx = CuckatooContext::new_impl(29, 42, 10).unwrap(); ctx.set_header_nonce([0u8; 80].to_vec(), Some(20), false)?; assert!(ctx.verify(&Proof::new(V1_29.to_vec())).is_ok()); Ok(()) } - fn validate31_vectors() -> Result<(), Error> - where - T: EdgeType, - { - let mut ctx = CuckatooContext::::new_impl(31, 42, 10).unwrap(); + fn validate31_vectors() -> Result<(), Error> { + let mut ctx = CuckatooContext::new_impl(31, 42, 10).unwrap(); ctx.set_header_nonce([0u8; 80].to_vec(), Some(99), false)?; assert!(ctx.verify(&Proof::new(V1_31.to_vec())).is_ok()); Ok(()) } - fn validate_fail() -> Result<(), Error> - where - T: EdgeType, - { - let mut ctx = CuckatooContext::::new_impl(29, 42, 10).unwrap(); + fn validate_fail() -> Result<(), Error> { + let mut ctx = CuckatooContext::new_impl(29, 42, 10).unwrap(); let mut header = [0u8; 80]; header[0] = 1u8; ctx.set_header_nonce(header.to_vec(), Some(20), false)?; @@ -440,10 +405,7 @@ mod test { Ok(()) } - fn basic_solve() -> Result<(), Error> - where - T: EdgeType, - { + fn basic_solve() -> Result<(), Error> { let nonce = 1546569; let _range = 1; let header = [0u8; 80].to_vec(); @@ -458,7 +420,7 @@ mod test { String::from_utf8(header.clone()).unwrap(), nonce ); - let mut ctx_u32 = CuckatooContext::::new_impl(edge_bits, proof_size, max_sols)?; + let mut ctx_u32 = CuckatooContext::new_impl(edge_bits, proof_size, max_sols)?; let mut bytes = ctx_u32.byte_count()?; let mut unit = 0; while bytes >= 10240 { diff --git a/core/src/pow/lean.rs b/core/src/pow/lean.rs index 64310dc5de..8d46efdae7 100644 --- a/core/src/pow/lean.rs +++ b/core/src/pow/lean.rs @@ -25,7 +25,7 @@ use crate::pow::Proof; /// Tromp's implementation, as it's not optimized for performance and reuses /// croaring which is likely sub-optimal for this task. pub struct Lean { - params: CuckooParams, + params: CuckooParams, edges: Bitmap, } @@ -33,7 +33,7 @@ impl Lean { /// Instantiates a new lean miner based on some Cuckatoo parameters pub fn new(edge_bits: u8) -> Lean { // note that proof size doesn't matter to a lean miner - let params = CuckooParams::new(edge_bits, 42).unwrap(); + let params = CuckooParams::new(edge_bits, edge_bits, 42).unwrap(); // edge bitmap, before trimming all of them are on let mut edges = Bitmap::create_with_capacity(params.num_edges as u32); @@ -58,7 +58,7 @@ impl Lean { /// Finds the Cuckatoo Cycles on the remaining edges. Delegates the finding /// to a context, passing the trimmed edges iterator. - pub fn find_cycles(&self, mut ctx: CuckatooContext) -> Result, Error> { + pub fn find_cycles(&self, mut ctx: CuckatooContext) -> Result, Error> { ctx.find_cycles_iter(self.edges.iter().map(|e| e as u64)) } @@ -68,15 +68,15 @@ impl Lean { let mut nodes = Bitmap::create(); // increment count for each node for e in self.edges.iter() { - let node = self.params.sipnode(e, uorv, false).unwrap(); - nodes.add(node); + let node = self.params.sipnode(e.into(), uorv).unwrap(); + nodes.add(node as u32); } // then kill edges with lone nodes (no neighbour at ^1) let mut to_kill = Bitmap::create(); for e in self.edges.iter() { - let node = self.params.sipnode(e, uorv, false).unwrap(); - if !nodes.contains(node ^ 1) { + let node = self.params.sipnode(e.into(), uorv).unwrap(); + if !nodes.contains((node ^ 1) as u32) { to_kill.add(e); } } @@ -102,7 +102,7 @@ mod test { lean.set_header_nonce(header.clone(), nonce); lean.trim(); - let mut ctx_u32 = CuckatooContext::::new_impl(edge_bits, 42, 10).unwrap(); + let mut ctx_u32 = CuckatooContext::new_impl(edge_bits, 42, 10).unwrap(); ctx_u32.set_header_nonce(header, Some(nonce), true).unwrap(); lean.find_cycles(ctx_u32).unwrap(); } diff --git a/core/src/pow/types.rs b/core/src/pow/types.rs index aee9957873..0f75c33bd8 100644 --- a/core/src/pow/types.rs +++ b/core/src/pow/types.rs @@ -15,7 +15,6 @@ use crate::consensus::{graph_weight, MIN_DIFFICULTY, SECOND_POW_EDGE_BITS}; use crate::core::hash::{DefaultHashable, Hashed}; use crate::global; -use crate::pow::common::EdgeType; use crate::pow::error::Error; use crate::ser::{self, Readable, Reader, Writeable, Writer}; use rand::{thread_rng, Rng}; @@ -28,10 +27,7 @@ use std::{fmt, iter}; /// Generic trait for a solver/verifier providing common interface into Cuckoo-family PoW /// Mostly used for verification, but also for test mining if necessary -pub trait PoWContext -where - T: EdgeType, -{ +pub trait PoWContext { /// Sets the header along with an optional nonce at the end /// solve: whether to set up structures for a solve (true) or just validate (false) fn set_header_nonce(