mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Demo lean miner, minor PoW improvements (#1630)
This commit is contained in:
parent
4d70968e70
commit
2259c18dd6
6 changed files with 239 additions and 91 deletions
|
@ -19,7 +19,7 @@
|
|||
use consensus::TargetError;
|
||||
use consensus::{
|
||||
BLOCK_TIME_SEC, COINBASE_MATURITY, CUT_THROUGH_HORIZON, DEFAULT_MIN_SIZESHIFT,
|
||||
DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY, MEDIAN_TIME_WINDOW, PROOFSIZE,
|
||||
DIFFICULTY_ADJUST_WINDOW, EASINESS, INITIAL_DIFFICULTY, MEDIAN_TIME_WINDOW, PROOFSIZE,
|
||||
REFERENCE_SIZESHIFT,
|
||||
};
|
||||
use pow::{self, CuckooContext, Difficulty, EdgeType, PoWContext};
|
||||
|
@ -123,7 +123,6 @@ pub fn set_mining_mode(mode: ChainTypes) {
|
|||
pub fn create_pow_context<T>(
|
||||
edge_bits: u8,
|
||||
proof_size: usize,
|
||||
easiness_pct: u32,
|
||||
max_sols: u32,
|
||||
) -> Result<Box<impl PoWContext<T>>, pow::Error>
|
||||
where
|
||||
|
@ -132,7 +131,7 @@ where
|
|||
// Perform whatever tests, configuration etc are needed to determine desired context + edge size
|
||||
// + params
|
||||
// Hardcode to regular cuckoo for now
|
||||
CuckooContext::<T>::new(edge_bits, proof_size, easiness_pct, max_sols)
|
||||
CuckooContext::<T>::new(edge_bits, proof_size, EASINESS, max_sols)
|
||||
// Or switch to cuckatoo as follows:
|
||||
// CuckatooContext::<T>::new(edge_bits, proof_size, easiness_pct, max_sols)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
//! Common types and traits for cuckoo/cuckatoo family of solvers
|
||||
|
||||
use blake2::blake2b::blake2b;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use pow::error::{Error, ErrorKind};
|
||||
use pow::num::{PrimInt, ToPrimitive};
|
||||
use pow::siphash::siphash24;
|
||||
|
@ -23,8 +25,6 @@ use std::io::Cursor;
|
|||
use std::ops::{BitOrAssign, Mul};
|
||||
use std::{fmt, mem};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
/// Operations needed for edge type (going to be u32 or u64)
|
||||
pub trait EdgeType: PrimInt + ToPrimitive + Mul + BitOrAssign + Hash {}
|
||||
impl EdgeType for u32 {}
|
||||
|
@ -100,29 +100,6 @@ pub fn create_siphash_keys(header: Vec<u8>) -> Result<[u64; 4], Error> {
|
|||
])
|
||||
}
|
||||
|
||||
/// Return siphash masked for type
|
||||
pub fn sipnode<T>(
|
||||
keys: &[u64; 4],
|
||||
edge: T,
|
||||
edge_mask: &T,
|
||||
uorv: u64,
|
||||
shift: bool,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
T: EdgeType,
|
||||
{
|
||||
let hash_u64 = siphash24(
|
||||
keys,
|
||||
2 * edge.to_u64().ok_or(ErrorKind::IntegerCast)? + uorv,
|
||||
);
|
||||
let mut masked = hash_u64 & edge_mask.to_u64().ok_or(ErrorKind::IntegerCast)?;
|
||||
if shift {
|
||||
masked = masked << 1;
|
||||
masked |= uorv;
|
||||
}
|
||||
Ok(T::from(masked).ok_or(ErrorKind::IntegerCast)?)
|
||||
}
|
||||
|
||||
/// Macros to clean up integer unwrapping
|
||||
#[macro_export]
|
||||
macro_rules! to_u64 {
|
||||
|
@ -151,3 +128,80 @@ macro_rules! to_edge {
|
|||
T::from($n).ok_or(ErrorKind::IntegerCast)?
|
||||
};
|
||||
}
|
||||
|
||||
/// Utility struct to calculate commonly used Cuckoo parameters calculated
|
||||
/// from header, nonce, sizeshift, etc.
|
||||
pub struct CuckooParams<T>
|
||||
where
|
||||
T: EdgeType,
|
||||
{
|
||||
pub edge_bits: u8,
|
||||
pub proof_size: usize,
|
||||
pub num_edges: u64,
|
||||
pub siphash_keys: [u64; 4],
|
||||
pub easiness: T,
|
||||
pub edge_mask: T,
|
||||
}
|
||||
|
||||
impl<T> CuckooParams<T>
|
||||
where
|
||||
T: EdgeType,
|
||||
{
|
||||
/// Instantiates new params and calculate easiness, edge mask, etc
|
||||
pub fn new(
|
||||
edge_bits: u8,
|
||||
proof_size: usize,
|
||||
easiness_pct: u32,
|
||||
cuckatoo: bool,
|
||||
) -> Result<CuckooParams<T>, Error> {
|
||||
let num_edges = 1 << edge_bits;
|
||||
let num_nodes = 2 * num_edges as u64;
|
||||
let easiness = if cuckatoo {
|
||||
to_u64!(easiness_pct) * num_nodes / 100
|
||||
} else {
|
||||
to_u64!(easiness_pct) * num_edges / 100
|
||||
};
|
||||
let edge_mask = if cuckatoo {
|
||||
to_edge!(num_edges - 1)
|
||||
} else {
|
||||
to_edge!(num_edges / 2 - 1)
|
||||
};
|
||||
Ok(CuckooParams {
|
||||
siphash_keys: [0; 4],
|
||||
easiness: to_edge!(easiness),
|
||||
proof_size,
|
||||
edge_mask,
|
||||
num_edges,
|
||||
edge_bits,
|
||||
})
|
||||
}
|
||||
|
||||
/// Reset the main keys used for siphash from the header and nonce
|
||||
pub fn reset_header_nonce(
|
||||
&mut self,
|
||||
mut header: Vec<u8>,
|
||||
nonce: Option<u32>,
|
||||
) -> Result<(), Error> {
|
||||
if let Some(n) = nonce {
|
||||
let len = header.len();
|
||||
header.truncate(len - mem::size_of::<u32>());
|
||||
header.write_u32::<LittleEndian>(n)?;
|
||||
}
|
||||
self.siphash_keys = set_header_nonce(header, nonce)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return siphash masked for type
|
||||
pub fn sipnode(&self, edge: T, uorv: u64, shift: bool) -> Result<T, Error> {
|
||||
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 = masked << 1;
|
||||
masked |= uorv;
|
||||
}
|
||||
Ok(T::from(masked).ok_or(ErrorKind::IntegerCast)?)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use std::mem;
|
|||
use byteorder::{BigEndian, LittleEndian, WriteBytesExt};
|
||||
use croaring::Bitmap;
|
||||
|
||||
use pow::common::{self, EdgeType, Link};
|
||||
use pow::common::{self, CuckooParams, EdgeType, Link};
|
||||
use pow::error::{Error, ErrorKind};
|
||||
use pow::{PoWContext, Proof};
|
||||
use util;
|
||||
|
@ -158,11 +158,8 @@ pub struct CuckatooContext<T>
|
|||
where
|
||||
T: EdgeType,
|
||||
{
|
||||
siphash_keys: [u64; 4],
|
||||
easiness: T,
|
||||
params: CuckooParams<T>,
|
||||
graph: Graph<T>,
|
||||
proof_size: usize,
|
||||
edge_mask: T,
|
||||
}
|
||||
|
||||
impl<T> PoWContext<T> for CuckatooContext<T>
|
||||
|
@ -193,7 +190,8 @@ where
|
|||
}
|
||||
|
||||
fn find_cycles(&mut self) -> Result<Vec<Proof>, Error> {
|
||||
self.find_cycles_impl()
|
||||
let ease = to_u64!(self.params.easiness);
|
||||
self.find_cycles_iter(0..ease)
|
||||
}
|
||||
|
||||
fn verify(&self, proof: &Proof) -> Result<(), Error> {
|
||||
|
@ -212,22 +210,18 @@ where
|
|||
easiness_pct: u32,
|
||||
max_sols: u32,
|
||||
) -> Result<CuckatooContext<T>, Error> {
|
||||
let num_edges = 1 << edge_bits;
|
||||
let num_nodes = 2 * num_edges as u64;
|
||||
let easiness = to_u64!(easiness_pct) * num_nodes / 100;
|
||||
let params = CuckooParams::new(edge_bits, proof_size, easiness_pct, true)?;
|
||||
let num_edges = to_edge!(params.num_edges);
|
||||
Ok(CuckatooContext {
|
||||
siphash_keys: [0; 4],
|
||||
easiness: to_edge!(easiness),
|
||||
graph: Graph::new(to_edge!(num_edges), max_sols, proof_size)?,
|
||||
proof_size: proof_size,
|
||||
edge_mask: to_edge!(num_edges - 1),
|
||||
params,
|
||||
graph: Graph::new(num_edges, max_sols, proof_size)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a siphash key as a hex string (for display convenience)
|
||||
pub fn sipkey_hex(&self, index: usize) -> Result<String, Error> {
|
||||
let mut rdr = vec![];
|
||||
rdr.write_u64::<BigEndian>(self.siphash_keys[index])?;
|
||||
rdr.write_u64::<BigEndian>(self.params.siphash_keys[index])?;
|
||||
Ok(util::to_hex(rdr))
|
||||
}
|
||||
|
||||
|
@ -239,16 +233,11 @@ where
|
|||
/// Set the header and optional nonce in the last part of the header
|
||||
pub fn set_header_nonce_impl(
|
||||
&mut self,
|
||||
mut header: Vec<u8>,
|
||||
header: Vec<u8>,
|
||||
nonce: Option<u32>,
|
||||
solve: bool,
|
||||
) -> Result<(), Error> {
|
||||
let len = header.len();
|
||||
header.truncate(len - mem::size_of::<u32>());
|
||||
if let Some(n) = nonce {
|
||||
header.write_u32::<LittleEndian>(n)?;
|
||||
}
|
||||
self.siphash_keys = common::set_header_nonce(header, nonce)?;
|
||||
self.params.reset_header_nonce(header, nonce)?;
|
||||
if solve {
|
||||
self.graph.reset()?;
|
||||
}
|
||||
|
@ -256,19 +245,26 @@ where
|
|||
}
|
||||
|
||||
/// Return siphash masked for type
|
||||
fn sipnode(&self, edge: T, uorv: u64) -> Result<T, Error> {
|
||||
common::sipnode::<T>(&self.siphash_keys, edge, &self.edge_mask, uorv, false)
|
||||
pub fn sipnode(&self, edge: T, uorv: u64) -> Result<T, Error> {
|
||||
self.params.sipnode(edge, uorv, false)
|
||||
}
|
||||
|
||||
/// Simple implementation of algorithm
|
||||
pub fn find_cycles_impl(&mut self) -> Result<Vec<Proof>, Error> {
|
||||
for n in 0..to_u64!(self.easiness) {
|
||||
|
||||
pub fn find_cycles_iter<'a, I>(&mut self, iter: I) -> Result<Vec<Proof>, Error>
|
||||
where
|
||||
I: Iterator<Item = u64>,
|
||||
{
|
||||
let mut val = vec![];
|
||||
for n in iter {
|
||||
val.push(n);
|
||||
let u = self.sipnode(to_edge!(n), 0)?;
|
||||
let v = self.sipnode(to_edge!(n), 1)?;
|
||||
self.graph.add_edge(to_edge!(u), to_edge!(v))?;
|
||||
}
|
||||
self.graph.solutions.pop();
|
||||
for s in &mut self.graph.solutions {
|
||||
s.nonces = map_vec!(s.nonces, |n| val[*n as usize]);
|
||||
s.nonces.sort();
|
||||
}
|
||||
for s in &self.graph.solutions {
|
||||
|
@ -286,11 +282,11 @@ where
|
|||
pub fn verify_impl(&self, proof: &Proof) -> Result<(), Error> {
|
||||
let nonces = &proof.nonces;
|
||||
let mut uvs = vec![0u64; 2 * proof.proof_size()];
|
||||
let mut xor0: u64 = (self.proof_size as u64 / 2) & 1;
|
||||
let mut xor0: u64 = (self.params.proof_size as u64 / 2) & 1;
|
||||
let mut xor1: u64 = xor0;
|
||||
|
||||
for n in 0..proof.proof_size() {
|
||||
if nonces[n] > to_u64!(self.edge_mask) {
|
||||
if nonces[n] > to_u64!(self.params.edge_mask) {
|
||||
return Err(ErrorKind::Verification("edge too big".to_owned()))?;
|
||||
}
|
||||
if n > 0 && nonces[n] <= nonces[n - 1] {
|
||||
|
@ -314,7 +310,7 @@ where
|
|||
j = i;
|
||||
let mut k = j;
|
||||
loop {
|
||||
k = (k + 2) % (2 * self.proof_size);
|
||||
k = (k + 2) % (2 * self.params.proof_size);
|
||||
if k == i {
|
||||
break;
|
||||
}
|
||||
|
@ -335,7 +331,7 @@ where
|
|||
break;
|
||||
}
|
||||
}
|
||||
if n == self.proof_size {
|
||||
if n == self.params.proof_size {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ErrorKind::Verification("cycle too short".to_owned()))?
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
//! simple miner is included, mostly for testing purposes. John Tromp's Tomato
|
||||
//! miner will be much faster in almost every environment.
|
||||
|
||||
use pow::common::{self, Edge, EdgeType};
|
||||
use pow::common::{self, CuckooParams, Edge, EdgeType};
|
||||
use pow::error::{Error, ErrorKind};
|
||||
use pow::num::ToPrimitive;
|
||||
use pow::{PoWContext, Proof};
|
||||
|
@ -32,11 +32,7 @@ pub struct CuckooContext<T>
|
|||
where
|
||||
T: EdgeType,
|
||||
{
|
||||
edge_bits: u8,
|
||||
siphash_keys: [u64; 4],
|
||||
easiness: T,
|
||||
proof_size: usize,
|
||||
edge_mask: T,
|
||||
params: CuckooParams<T>,
|
||||
graph: Vec<T>,
|
||||
_max_sols: u32,
|
||||
}
|
||||
|
@ -88,22 +84,17 @@ where
|
|||
easiness_pct: u32,
|
||||
max_sols: u32,
|
||||
) -> Result<CuckooContext<T>, Error> {
|
||||
let num_edges = 1 << edge_bits;
|
||||
let easiness = to_u64!(easiness_pct) * num_edges / 100;
|
||||
let params = CuckooParams::new(edge_bits, proof_size, easiness_pct, false)?;
|
||||
let num_edges = params.num_edges as usize;
|
||||
Ok(CuckooContext {
|
||||
edge_bits: edge_bits,
|
||||
siphash_keys: [0; 4],
|
||||
easiness: to_edge!(easiness),
|
||||
proof_size: proof_size,
|
||||
edge_mask: to_edge!(num_edges / 2 - 1),
|
||||
graph: vec![T::zero(); num_edges as usize + 1],
|
||||
params: params,
|
||||
graph: vec![T::zero(); num_edges + 1],
|
||||
_max_sols: max_sols,
|
||||
})
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<(), Error> {
|
||||
let num_edges = 1 << self.edge_bits;
|
||||
self.graph = vec![T::zero(); num_edges + 1];
|
||||
self.graph = vec![T::zero(); self.params.num_edges as usize + 1];
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -115,7 +106,7 @@ where
|
|||
nonce: Option<u32>,
|
||||
solve: bool,
|
||||
) -> Result<(), Error> {
|
||||
self.siphash_keys = common::set_header_nonce(header, nonce)?;
|
||||
self.params.reset_header_nonce(header, nonce)?;
|
||||
if solve {
|
||||
self.reset()?;
|
||||
}
|
||||
|
@ -126,7 +117,7 @@ where
|
|||
/// simply materialized as a u64 from a nonce and an offset (generally 0 or
|
||||
/// 1).
|
||||
fn new_node(&self, edge: T, uorv: u64) -> Result<T, Error> {
|
||||
common::sipnode::<T>(&self.siphash_keys, edge, &self.edge_mask, uorv, true)
|
||||
self.params.sipnode(edge, uorv, true)
|
||||
}
|
||||
|
||||
/// Creates a new edge in the cuckoo graph generated by our seed from a
|
||||
|
@ -193,7 +184,7 @@ where
|
|||
nu += 1;
|
||||
nv += 1;
|
||||
}
|
||||
if nu + nv + 1 == self.proof_size {
|
||||
if nu + nv + 1 == self.params.proof_size {
|
||||
self.solution(&us, nu as u64, &vs, nv as u64)
|
||||
} else {
|
||||
Err(ErrorKind::InvalidCycle(nu + nv + 1))?
|
||||
|
@ -223,8 +214,8 @@ where
|
|||
});
|
||||
}
|
||||
let mut n = 0;
|
||||
let mut sol = vec![T::zero(); self.proof_size];
|
||||
for nonce in 0..to_usize!(self.easiness) {
|
||||
let mut sol = vec![T::zero(); self.params.proof_size];
|
||||
for nonce in 0..to_usize!(self.params.easiness) {
|
||||
let edge = self.new_edge(to_edge!(nonce))?;
|
||||
if cycle.contains(&edge) {
|
||||
sol[n] = to_edge!(nonce);
|
||||
|
@ -232,7 +223,7 @@ where
|
|||
cycle.remove(&edge);
|
||||
}
|
||||
}
|
||||
return if n == self.proof_size {
|
||||
return if n == self.params.proof_size {
|
||||
Ok(sol)
|
||||
} else {
|
||||
Err(ErrorKind::NoCycle)?
|
||||
|
@ -243,7 +234,7 @@ where
|
|||
pub fn find_cycles_impl(&mut self) -> Result<Vec<Proof>, Error> {
|
||||
let mut us = [T::zero(); MAXPATHLEN];
|
||||
let mut vs = [T::zero(); MAXPATHLEN];
|
||||
for nonce in 0..to_usize!(self.easiness) {
|
||||
for nonce in 0..to_usize!(self.params.easiness) {
|
||||
us[0] = self.new_node(to_edge!(nonce), 0)?;
|
||||
vs[0] = self.new_node(to_edge!(nonce), 1)?;
|
||||
let u = self.graph[to_usize!(us[0])];
|
||||
|
@ -258,7 +249,7 @@ where
|
|||
match sol {
|
||||
Ok(s) => {
|
||||
let mut proof = Proof::new(map_vec!(s.to_vec(), |&n| n.to_u64().unwrap_or(0)));
|
||||
proof.cuckoo_sizeshift = self.edge_bits;
|
||||
proof.cuckoo_sizeshift = self.params.edge_bits;
|
||||
return Ok(vec![proof]);
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
|
@ -275,7 +266,7 @@ where
|
|||
/// nonces form a cycle in a Cuckoo graph. Each nonce generates an edge, we
|
||||
/// build the nodes on both side of that edge and count the connections.
|
||||
pub fn verify_impl(&self, proof: &Proof) -> Result<(), Error> {
|
||||
let easiness = to_u64!(self.easiness);
|
||||
let easiness = to_u64!(self.params.easiness);
|
||||
let nonces = &proof.nonces;
|
||||
let mut us = vec![T::zero(); proof.proof_size()];
|
||||
let mut vs = vec![T::zero(); proof.proof_size()];
|
||||
|
|
111
core/src/pow/lean.rs
Normal file
111
core/src/pow/lean.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Lean miner for Cuckatoo Cycle
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use croaring::Bitmap;
|
||||
|
||||
use pow::common::CuckooParams;
|
||||
use pow::cuckatoo::CuckatooContext;
|
||||
use pow::error::{Error, ErrorKind};
|
||||
use pow::siphash::siphash24;
|
||||
use pow::{PoWContext, Proof};
|
||||
|
||||
/// Lean miner implementation aiming to be as short and simple as possible.
|
||||
/// As a consequence, it's a little less than 10 times slower than John
|
||||
/// 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<u32>,
|
||||
edges: Bitmap,
|
||||
}
|
||||
|
||||
impl Lean {
|
||||
/// Instantiates a new lean miner based on some Cuckatoo parameters
|
||||
pub fn new(edge_bits: u8, easiness_pct: u32) -> Lean {
|
||||
// note that proof size doesn't matter to a lean miner
|
||||
let params = CuckooParams::new(edge_bits, 42, easiness_pct, true).unwrap();
|
||||
|
||||
// edge bitmap, before trimming all of them are on
|
||||
let mut edges = Bitmap::create_with_capacity(params.easiness);
|
||||
edges.flip_inplace(0..params.easiness.into());
|
||||
|
||||
Lean { params, edges }
|
||||
}
|
||||
|
||||
/// Sets the header and nonce to seed the graph
|
||||
pub fn set_header_nonce(&mut self, header: Vec<u8>, nonce: u32) {
|
||||
self.params.reset_header_nonce(header, Some(nonce)).unwrap();
|
||||
}
|
||||
|
||||
/// Trim edges in the Cuckatoo graph. This applies multiple trimming rounds
|
||||
/// and works well for Cuckatoo size above 18.
|
||||
pub fn trim(&mut self) {
|
||||
// trimming successively
|
||||
while self.edges.cardinality() > (7 * (self.params.easiness >> 8) / 8) as u64 {
|
||||
self.count_and_kill();
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<u32>) -> Result<Vec<Proof>, Error> {
|
||||
ctx.find_cycles_iter(self.edges.iter().map(|e| e as u64))
|
||||
}
|
||||
|
||||
fn count_and_kill(&mut self) {
|
||||
// on each side u or v of the bipartite graph
|
||||
for uorv in 0..2 {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
to_kill.add(e);
|
||||
}
|
||||
}
|
||||
self.edges.andnot_inplace(&to_kill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use pow::common;
|
||||
use pow::cuckatoo::*;
|
||||
|
||||
#[test]
|
||||
fn lean_miner() {
|
||||
let nonce = 15465723;
|
||||
let header = [0u8; 84].to_vec(); // with nonce
|
||||
let edge_bits = 19;
|
||||
|
||||
let mut lean = Lean::new(edge_bits, 50);
|
||||
lean.set_header_nonce(header.clone(), nonce);
|
||||
lean.trim();
|
||||
|
||||
let mut ctx_u32 = CuckatooContext::<u32>::new_impl(edge_bits, 42, 50, 10).unwrap();
|
||||
ctx_u32.set_header_nonce(header, Some(nonce), true).unwrap();
|
||||
lean.find_cycles(ctx_u32).unwrap();
|
||||
}
|
||||
}
|
|
@ -41,6 +41,8 @@ mod common;
|
|||
pub mod cuckatoo;
|
||||
pub mod cuckoo;
|
||||
mod error;
|
||||
#[allow(dead_code)]
|
||||
pub mod lean;
|
||||
mod siphash;
|
||||
mod types;
|
||||
|
||||
|
@ -61,12 +63,8 @@ const MAX_SOLS: u32 = 10;
|
|||
/// Validates the proof of work of a given header, and that the proof of work
|
||||
/// satisfies the requirements of the header.
|
||||
pub fn verify_size(bh: &BlockHeader, cuckoo_sz: u8) -> Result<(), Error> {
|
||||
let mut ctx = global::create_pow_context::<u64>(
|
||||
cuckoo_sz,
|
||||
bh.pow.proof.nonces.len(),
|
||||
consensus::EASINESS,
|
||||
MAX_SOLS,
|
||||
)?;
|
||||
let mut ctx =
|
||||
global::create_pow_context::<u64>(cuckoo_sz, bh.pow.proof.nonces.len(), MAX_SOLS)?;
|
||||
ctx.set_header_nonce(bh.pre_pow(), None, false)?;
|
||||
ctx.verify(&bh.pow.proof)
|
||||
}
|
||||
|
@ -109,8 +107,7 @@ pub fn pow_size(
|
|||
loop {
|
||||
// if we found a cycle (not guaranteed) and the proof hash is higher that the
|
||||
// diff, we're all good
|
||||
let mut ctx =
|
||||
global::create_pow_context::<u32>(sz, proof_size, consensus::EASINESS, MAX_SOLS)?;
|
||||
let mut ctx = global::create_pow_context::<u32>(sz, proof_size, MAX_SOLS)?;
|
||||
ctx.set_header_nonce(bh.pre_pow(), None, true)?;
|
||||
if let Ok(proofs) = ctx.find_cycles() {
|
||||
bh.pow.proof = proofs[0].clone();
|
||||
|
|
Loading…
Reference in a new issue