Cuckoo miner integration, Queue implementation (#84)

* Adding ability to serialise parts of the header, pre-nonce and post-nonce
* Some test integration of queueing functions in cuckoo-miner
* more cuckoo-miner async mode integration, now more or less working
* integrating async miner workflow
* rocksdb update
* u64 internal difficulty representation, and integration of latest Cuckoo-miner API
* change to cuckoo-miner notify function
* Issue in testing, and if use_async value is None in grin.toml
* making async mode explicit in tests - 2
* fiddle with port numbers for CI
* update tag to ensure cuckoo-miner build doesn't fail on windows
* change the order in which tests are run
This commit is contained in:
Yeastplume
2017-08-03 17:57:55 +01:00
committed by Ignotus Peverell
parent c994c7cba2
commit cdf4203dd1
14 changed files with 392 additions and 144 deletions
+25 -20
View File
@@ -30,7 +30,7 @@ pub const REWARD: u64 = 1_000_000_000;
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: i64 = 60;
pub const BLOCK_TIME_SEC: u64 = 60;
/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;
@@ -61,22 +61,22 @@ pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);
pub const MAX_MSG_LEN: u64 = 20_000_000;
/// The minimum mining difficulty we'll allow
pub const MINIMUM_DIFFICULTY: u32 = 10;
pub const MINIMUM_DIFFICULTY: u64 = 10;
/// Time window in blocks to calculate block time median
pub const MEDIAN_TIME_WINDOW: u32 = 11;
pub const MEDIAN_TIME_WINDOW: u64 = 11;
/// Number of blocks used to calculate difficulty adjustments
pub const DIFFICULTY_ADJUST_WINDOW: u32 = 23;
pub const DIFFICULTY_ADJUST_WINDOW: u64 = 23;
/// Average time span of the difficulty adjustment window
pub const BLOCK_TIME_WINDOW: i64 = (DIFFICULTY_ADJUST_WINDOW as i64) * BLOCK_TIME_SEC;
pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC;
/// Maximum size time window used for difficutly adjustments
pub const UPPER_TIME_BOUND: i64 = BLOCK_TIME_WINDOW * 4 / 3;
pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 4 / 3;
/// Minimum size time window used for difficutly adjustments
pub const LOWER_TIME_BOUND: i64 = BLOCK_TIME_WINDOW * 5 / 6;
pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 5 / 6;
/// Error when computing the next difficulty adjustment.
#[derive(Debug, Clone)]
@@ -100,7 +100,7 @@ impl fmt::Display for TargetError {
/// difference between the median timestamps at the beginning and the end
/// of the window.
pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
where T: IntoIterator<Item = Result<(i64, Difficulty), TargetError>>
where T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>
{
// Block times at the begining and end of the adjustment window, used to
@@ -113,7 +113,7 @@ pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
// Enumerating backward over blocks
for (n, head_info) in cursor.into_iter().enumerate() {
let m = n as u32;
let m = n as u64;
let (ts, diff) = head_info?;
// Sum each element in the adjustment window. In addition, retain
@@ -156,10 +156,13 @@ pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
ts_damp
};
Ok(diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW as u32) /
Difficulty::from_num(adj_ts as u32))
Ok(diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) /
Difficulty::from_num(adj_ts))
}
#[cfg(test)]
use std;
#[cfg(test)]
mod test {
use core::target::Difficulty;
@@ -168,18 +171,20 @@ mod test {
// Builds an iterator for next difficulty calculation with the provided
// constant time interval, difficulty and total length.
fn repeat(interval: i64, diff: u32, len: u32) -> Vec<Result<(i64, Difficulty), TargetError>> {
fn repeat(interval: u64, diff: u64, len: u64) -> Vec<Result<(u64, Difficulty), TargetError>> {
//watch overflow here, length shouldn't be ridiculous anyhow
assert!(len < std::usize::MAX as u64);
let diffs = vec![Difficulty::from_num(diff); len as usize];
let times = (0..(len as usize)).map(|n| (n as i64) * interval).rev();
let times = (0..(len as usize)).map(|n| n * interval as usize).rev();
let pairs = times.zip(diffs.iter());
pairs.map(|(t, d)| Ok((t, d.clone()))).collect::<Vec<_>>()
pairs.map(|(t, d)| Ok((t as u64, d.clone()))).collect::<Vec<_>>()
}
fn repeat_offs(from: i64,
interval: i64,
diff: u32,
len: u32)
-> Vec<Result<(i64, Difficulty), TargetError>> {
fn repeat_offs(from: u64,
interval: u64,
diff: u64,
len: u64)
-> Vec<Result<(u64, Difficulty), TargetError>> {
map_vec!(repeat(interval, diff, len), |e| {
match e.clone() {
Err(e) => Err(e),
@@ -209,7 +214,7 @@ mod test {
// checking averaging works, window length is odd so need to compensate a little
let sec = DIFFICULTY_ADJUST_WINDOW / 2 + 1 + MEDIAN_TIME_WINDOW;
let mut s1 = repeat(60, 500, sec);
let mut s2 = repeat_offs((sec * 60) as i64, 60, 1545, DIFFICULTY_ADJUST_WINDOW / 2);
let mut s2 = repeat_offs((sec * 60) as u64, 60, 1545, DIFFICULTY_ADJUST_WINDOW / 2);
s2.append(&mut s1);
assert_eq!(next_difficulty(s2).unwrap(), Difficulty::from_num(999));
+29 -30
View File
@@ -15,60 +15,61 @@
//! Definition of the maximum target value a proof-of-work block hash can have
//! and
//! the related difficulty, defined as the maximum target divided by the hash.
//!
//! Note this is now wrapping a simple U64 now, but it's desirable to keep the
//! wrapper in case the internal representation needs to change again
use std::fmt;
use std::ops::{Add, Mul, Div, Sub};
use std::io::Cursor;
use std::u64::MAX;
use bigint::BigUint;
use serde::{Serialize, Serializer, Deserialize, Deserializer, de};
use byteorder::{ByteOrder, ReadBytesExt, BigEndian};
use core::hash::Hash;
use ser::{self, Reader, Writer, Writeable, Readable};
/// The target is the 32-bytes hash block hashes must be lower than.
pub const MAX_TARGET: [u8; 32] = [0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
pub const MAX_TARGET: [u8; 8] = [0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
/// The difficulty is defined as the maximum target divided by the block hash.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct Difficulty {
num: BigUint,
num: u64,
}
impl Difficulty {
/// Difficulty of zero, which is practically invalid (not target can be
/// calculated from it) but very useful as a start for additions.
pub fn zero() -> Difficulty {
Difficulty { num: BigUint::new(vec![0]) }
Difficulty { num: 0 }
}
/// Difficulty of one, which is the minumum difficulty (when the hash
/// equals the max target)
pub fn one() -> Difficulty {
Difficulty { num: BigUint::new(vec![1]) }
Difficulty { num: 1 }
}
/// Convert a `u32` into a `Difficulty`
pub fn from_num(num: u32) -> Difficulty {
Difficulty { num: BigUint::new(vec![num]) }
}
/// Convert a `BigUint` into a `Difficulty`
pub fn from_biguint(num: BigUint) -> Difficulty {
pub fn from_num(num: u64) -> Difficulty {
Difficulty { num: num }
}
/// Computes the difficulty from a hash. Divides the maximum target by the
/// provided hash.
pub fn from_hash(h: &Hash) -> Difficulty {
let max_target = BigUint::from_bytes_be(&MAX_TARGET);
let h_num = BigUint::from_bytes_be(&h[..]);
Difficulty { num: max_target / h_num }
let max_target = BigEndian::read_u64(&MAX_TARGET);
//Use the first 64 bits of the given hash
let mut in_vec=h.to_vec();
in_vec.truncate(8);
let num = BigEndian::read_u64(&in_vec);
Difficulty { num: max_target / num }
}
/// Converts the difficulty into a bignum
pub fn into_biguint(self) -> BigUint {
/// Converts the difficulty into a u64
pub fn into_num(&self) -> u64 {
self.num
}
}
@@ -109,17 +110,14 @@ impl Div<Difficulty> for Difficulty {
impl Writeable for Difficulty {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
let data = self.num.to_bytes_be();
try!(writer.write_u8(data.len() as u8));
writer.write_fixed_bytes(&data)
writer.write_u64(self.num)
}
}
impl Readable for Difficulty {
fn read(reader: &mut Reader) -> Result<Difficulty, ser::Error> {
let dlen = try!(reader.read_u8());
let data = try!(reader.read_fixed_bytes(dlen as usize));
Ok(Difficulty { num: BigUint::from_bytes_be(&data[..]) })
let data = try!(reader.read_u64());
Ok(Difficulty { num: data })
}
}
@@ -127,7 +125,7 @@ impl Serialize for Difficulty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_str(self.num.to_str_radix(10).as_str())
serializer.serialize_u64(self.num)
}
}
@@ -135,7 +133,7 @@ impl<'de> Deserialize<'de> for Difficulty {
fn deserialize<D>(deserializer: D) -> Result<Difficulty, D::Error>
where D: Deserializer<'de>
{
deserializer.deserialize_i32(DiffVisitor)
deserializer.deserialize_u64(DiffVisitor)
}
}
@@ -151,9 +149,10 @@ impl<'de> de::Visitor<'de> for DiffVisitor {
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where E: de::Error
{
let bigui = BigUint::parse_bytes(s.as_bytes(), 10).ok_or_else(|| {
de::Error::invalid_value(de::Unexpected::Str(s), &"a value number")
})?;
Ok(Difficulty { num: bigui })
let num_in = s.parse::<u64>();
if let Err(e)=num_in {
return Err(de::Error::invalid_value(de::Unexpected::Str(s), &"a value number"));
};
Ok(Difficulty { num: num_in.unwrap() })
}
}
+68 -14
View File
@@ -387,18 +387,72 @@ impl Writeable for [u8; 4] {
}
/// Useful marker trait on types that can be sized byte slices
pub trait AsFixedBytes: Sized + AsRef<[u8]> {}
pub trait AsFixedBytes: Sized + AsRef<[u8]> {
fn len(&self) -> usize;
}
impl<'a> AsFixedBytes for &'a [u8] {}
impl AsFixedBytes for Vec<u8> {}
impl AsFixedBytes for [u8; 1] {}
impl AsFixedBytes for [u8; 2] {}
impl AsFixedBytes for [u8; 4] {}
impl AsFixedBytes for [u8; 8] {}
impl AsFixedBytes for [u8; 32] {}
impl AsFixedBytes for String {}
impl AsFixedBytes for ::core::hash::Hash {}
impl AsFixedBytes for ::secp::pedersen::RangeProof {}
impl AsFixedBytes for ::secp::key::SecretKey {}
impl AsFixedBytes for ::secp::Signature {}
impl AsFixedBytes for ::secp::pedersen::Commitment {}
impl<'a> AsFixedBytes for &'a [u8] {
fn len(&self) -> usize {
return 1;
}
}
impl AsFixedBytes for Vec<u8> {
fn len(&self) -> usize {
return self.len();
}
}
impl AsFixedBytes for [u8; 1] {
fn len(&self) -> usize {
return 1;
}
}
impl AsFixedBytes for [u8; 2] {
fn len(&self) -> usize {
return 2;
}
}
impl AsFixedBytes for [u8; 4] {
fn len(&self) -> usize {
return 4;
}
}
impl AsFixedBytes for [u8; 8] {
fn len(&self) -> usize {
return 8;
}
}
impl AsFixedBytes for [u8; 32] {
fn len(&self) -> usize {
return 32;
}
}
impl AsFixedBytes for String {
fn len(&self) -> usize {
return self.len();
}
}
impl AsFixedBytes for ::core::hash::Hash {
fn len(&self) -> usize {
return 32;
}
}
impl AsFixedBytes for ::secp::pedersen::RangeProof {
fn len(&self) -> usize {
return self.plen;
}
}
impl AsFixedBytes for ::secp::key::SecretKey {
fn len(&self) -> usize {
return 1;
}
}
impl AsFixedBytes for ::secp::Signature {
fn len(&self) -> usize {
return 64;
}
}
impl AsFixedBytes for ::secp::pedersen::Commitment {
fn len(&self) -> usize {
return PEDERSEN_COMMITMENT_SIZE;
}
}