equihash working
This commit is contained in:
parent
4365a54099
commit
70a8770f13
|
@ -61,7 +61,7 @@ name = "base64"
|
|||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -69,7 +69,7 @@ dependencies = [
|
|||
name = "bencher"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chain 0.1.0",
|
||||
"db 0.1.0",
|
||||
"network 0.1.0",
|
||||
|
@ -85,7 +85,7 @@ name = "bigint"
|
|||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -121,9 +121,19 @@ name = "bitflags"
|
|||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "blake2-rfc"
|
||||
version = "0.2.18"
|
||||
source = "git+https://github.com/gtank/blake2-rfc.git?branch=persona#c7c458429c429b81fea845421f5ab859710fa8af"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.1.0"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -131,7 +141,7 @@ name = "bytes"
|
|||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -181,6 +191,11 @@ dependencies = [
|
|||
"yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.2.0"
|
||||
|
@ -217,7 +232,7 @@ name = "csv"
|
|||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -255,7 +270,7 @@ name = "domain"
|
|||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -614,7 +629,7 @@ name = "message"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitcrypto 0.1.0",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chain 0.1.0",
|
||||
"network 0.1.0",
|
||||
"primitives 0.1.0",
|
||||
|
@ -635,7 +650,7 @@ name = "miner"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitcrypto 0.1.0",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chain 0.1.0",
|
||||
"db 0.1.0",
|
||||
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -683,7 +698,7 @@ name = "murmur3"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -864,7 +879,7 @@ name = "primitives"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bigint 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1125,7 +1140,7 @@ dependencies = [
|
|||
name = "serialization"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"primitives 0.1.0",
|
||||
]
|
||||
|
||||
|
@ -1221,7 +1236,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcrypto 0.1.0",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chain 0.1.0",
|
||||
"db 0.1.0",
|
||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1421,6 +1436,8 @@ name = "verification"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitcrypto 0.1.0",
|
||||
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?branch=persona)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chain 0.1.0",
|
||||
"db 0.1.0",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1516,12 +1533,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
|
||||
"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?branch=persona)" = "<none>"
|
||||
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
|
||||
"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
|
||||
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
|
||||
"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
|
|
|
@ -248,6 +248,7 @@ impl<F> BlockHeaderBuilder<F> where F: Invoke<chain::BlockHeader> {
|
|||
nonce: self.nonce,
|
||||
merkle_root_hash: self.merkle_root,
|
||||
version: self.version,
|
||||
equihash_solution: None,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -335,6 +336,7 @@ impl<F> TransactionBuilder<F> where F: Invoke<chain::Transaction> {
|
|||
version: self.version,
|
||||
inputs: self.inputs,
|
||||
outputs: self.outputs,
|
||||
joint_split: None,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ lazy_static = "1.0"
|
|||
log = "0.4"
|
||||
rayon = "1.0"
|
||||
parking_lot = "0.4"
|
||||
blake2-rfc = { version = "0.2.18" }
|
||||
blake2-rfc = { git = "https://github.com/gtank/blake2-rfc.git", branch = "persona" }
|
||||
byteorder = "1.2"
|
||||
primitives = { path = "../primitives" }
|
||||
chain = { path = "../chain" }
|
||||
serialization = { path = "../serialization" }
|
||||
|
|
|
@ -506,6 +506,7 @@ mod tests {
|
|||
.into_bytes(),
|
||||
}],
|
||||
lock_time: 0xffffffff,
|
||||
joint_split: None,
|
||||
}.into();
|
||||
|
||||
assert_eq!(transaction.raw.outputs[0].script_pubkey.len(), 46 + 2);
|
||||
|
|
|
@ -294,6 +294,7 @@ mod tests {
|
|||
time: time,
|
||||
bits: 0.into(),
|
||||
nonce: height,
|
||||
equihash_solution: None,
|
||||
};
|
||||
previous_header_hash = header.hash();
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// https://github.com/zcash/zcash/commit/fdda3c5085199d2c2170887aa064fc42afdb0360
|
||||
|
||||
use blake2_rfc::blake2b::Blake2b;
|
||||
use byteorder::{BigEndian, LittleEndian, ByteOrder, WriteBytesExt};
|
||||
use primitives::hex::ToHex;
|
||||
|
||||
pub struct EquihashParams {
|
||||
pub N: u32,
|
||||
|
@ -8,12 +10,32 @@ pub struct EquihashParams {
|
|||
}
|
||||
|
||||
impl EquihashParams {
|
||||
pub fn indices_per_hash_output(&self) -> usize {
|
||||
(512 / self.N) as usize
|
||||
}
|
||||
|
||||
pub fn hash_output(&self) -> usize {
|
||||
(self.indices_per_hash_output() * self.N as usize / 8usize) as usize
|
||||
}
|
||||
|
||||
pub fn collision_bit_length(&self) -> usize {
|
||||
self.N / (self.K + 1)
|
||||
(self.N / (self.K + 1)) as usize
|
||||
}
|
||||
|
||||
pub fn collision_byte_length(&self) -> usize {
|
||||
(self.collision_bit_length() + 7) / 8
|
||||
}
|
||||
|
||||
pub fn final_full_width(&self) -> usize {
|
||||
2 * self.collision_byte_length() + 4 * (1 << self.K)
|
||||
}
|
||||
|
||||
pub fn solution_size(&self) -> usize {
|
||||
(1usize << self.K) * (self.collision_bit_length() + 1) / 8
|
||||
((1usize << self.K) * (self.collision_bit_length() + 1) / 8) as usize
|
||||
}
|
||||
|
||||
pub fn hash_length(&self) -> usize {
|
||||
(self.K as usize + 1) * self.collision_byte_length()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,32 +44,273 @@ pub fn verify_equihash_solution(params: &EquihashParams, input: &[u8], solution:
|
|||
return false;
|
||||
}
|
||||
|
||||
let mut context = Blake2b::new(64);
|
||||
let mut context = new_blake2(params);
|
||||
context.update(input);
|
||||
|
||||
// pure equihash
|
||||
|
||||
let collision_bit_length = params.collision_bit_length();
|
||||
let indices = get_indices_from_minimal(solution, collision_bit_length);
|
||||
|
||||
let mut rows = Vec::new();
|
||||
for idx in indices {
|
||||
let hash = generate_hash(&context, (idx as usize / params.indices_per_hash_output()) as u32);
|
||||
let hash_begin = (idx as usize % params.indices_per_hash_output()) * params.N as usize / 8;
|
||||
let hash_end = hash_begin + params.N as usize / 8;
|
||||
|
||||
let mut row = vec![0; params.final_full_width()];
|
||||
let expanded_hash = expand_array(
|
||||
&hash[hash_begin..hash_end],
|
||||
params.collision_bit_length(),
|
||||
0);
|
||||
row[0..expanded_hash.len()].clone_from_slice(&expanded_hash);
|
||||
row[params.hash_length()..params.hash_length() + 4].clone_from_slice(&to_big_endian(idx));
|
||||
rows.push(row);
|
||||
}
|
||||
|
||||
let mut hash_len = params.hash_length();
|
||||
let mut indices_len = 4;
|
||||
while rows.len() > 1 {
|
||||
let mut rows_check = Vec::new();
|
||||
for i in 0..rows.len() / 2 {
|
||||
let row1 = &rows[i * 2];
|
||||
let row2 = &rows[i * 2 + 1];
|
||||
if !has_collision(row1, row2, params.collision_byte_length()) {
|
||||
return false;
|
||||
}
|
||||
if indices_before(row2, row1, hash_len, indices_len) {
|
||||
return false;
|
||||
}
|
||||
if !distinct_indices(row1, row2, hash_len, indices_len) {
|
||||
return false;
|
||||
}
|
||||
rows_check.push(merge_rows(row1, row2, hash_len, indices_len, params.collision_byte_length()));
|
||||
}
|
||||
|
||||
rows = rows_check;
|
||||
hash_len -= params.collision_byte_length();
|
||||
indices_len *= 2;
|
||||
}
|
||||
|
||||
rows[0].iter().take(hash_len).all(|x| *x == 0)
|
||||
}
|
||||
|
||||
fn merge_rows(row1: &[u8], row2: &[u8], len: usize, indices_len: usize, trim: usize) -> Vec<u8> {
|
||||
let mut row = row1.to_vec();
|
||||
for i in trim..len {
|
||||
row[i - trim] = row1[i] ^ row2[i];
|
||||
}
|
||||
|
||||
if indices_before(row1, row2, len, indices_len) {
|
||||
row[len - trim..len - trim + indices_len]
|
||||
.clone_from_slice(&row1[len..len + indices_len]);
|
||||
row[len - trim + indices_len..len - trim + indices_len + indices_len]
|
||||
.clone_from_slice(&row2[len..len + indices_len]);
|
||||
} else {
|
||||
row[len - trim..len - trim + indices_len]
|
||||
.clone_from_slice(&row2[len..len + indices_len]);
|
||||
row[len - trim + indices_len..len - trim + indices_len + indices_len]
|
||||
.clone_from_slice(&row1[len..len + indices_len]);
|
||||
}
|
||||
|
||||
row
|
||||
}
|
||||
|
||||
fn distinct_indices(row1: &[u8], row2: &[u8], len: usize, indices_len: usize) -> bool {
|
||||
for i in 0..indices_len / 4 {
|
||||
for j in 0..indices_len / 4 {
|
||||
if row1[len + i..len + i + 4] == row2[len + j..len + j + 4] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn has_collision(row1: &[u8], row2: &[u8], collision_byte_length: usize) -> bool {
|
||||
for i in 0..collision_byte_length {
|
||||
if row1[i] != row2[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn indices_before(row1: &[u8], row2: &[u8], len: usize, indices_len: usize) -> bool {
|
||||
for i in 0..indices_len {
|
||||
if row1[len + i] < row2[len + i] {
|
||||
return true;
|
||||
} else if row1[len + i] > row2[len + i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn generate_hash(context: &Blake2b, g: u32) -> Vec<u8> {
|
||||
let mut context = context.clone();
|
||||
context.update(&to_little_endian(g));
|
||||
context.finalize().as_bytes().to_vec()
|
||||
}
|
||||
|
||||
fn get_indices_from_minimal(solution: &[u8], collision_bit_length: usize) -> Vec<u32> {
|
||||
let indices_len = 8 * 4 * solution.len() / (collision_bit_length + 1);
|
||||
let byte_pad = 4 - ((collision_bit_length + 1 + 7) / 8);
|
||||
let mut array = Vec::new();
|
||||
let array = expand_array(solution, collision_bit_length + 1, byte_pad);
|
||||
|
||||
let mut ret = Vec::new();
|
||||
for i in 0..indices_len / 4 {
|
||||
ret.push(array_to_eh_index(&array[i*4..i*4 + 4]));
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
fn expand_array(data: &[u8], array: &mut Vec<u8>, bit_len: usize, byte_pad: usize) {
|
||||
fn get_minimal_from_indices(indices: &[u32], collision_bit_length: usize) -> Vec<u8> {
|
||||
let indices_len = indices.len() * 4;
|
||||
let min_len = (collision_bit_length + 1) * indices_len / (8 * 4);
|
||||
let byte_pad = 4 - ((collision_bit_length + 1) + 7) / 8;
|
||||
|
||||
let mut array = Vec::new();
|
||||
for i in 0..indices.len() {
|
||||
let mut be_index = Vec::new();
|
||||
be_index.write_u32::<BigEndian>(indices[i]).unwrap();
|
||||
array.extend(be_index);
|
||||
}
|
||||
|
||||
let mut ret = vec![0u8; min_len];
|
||||
compress_array(&array, &mut ret, collision_bit_length + 1, byte_pad);
|
||||
ret
|
||||
}
|
||||
|
||||
fn array_to_eh_index(data: &[u8]) -> u32 {
|
||||
BigEndian::read_u32(data)
|
||||
}
|
||||
|
||||
fn expand_array(data: &[u8], bit_len: usize, byte_pad: usize) -> Vec<u8> {
|
||||
let mut array = Vec::new();
|
||||
let out_width = (bit_len + 7) / 8 + byte_pad;
|
||||
let bit_len_mask = (1u32 << bit_len) - 1;
|
||||
|
||||
// The acc_bits least-significant bits of acc_value represent a bit sequence
|
||||
// in big-endian order.
|
||||
let mut acc_bits = 0usize;
|
||||
let mut acc_value = 0u32;
|
||||
|
||||
let mut j = 0usize;
|
||||
for i in 0usize..data.len() {
|
||||
acc_value = (acc_value << 8) | (data[i] as u32);
|
||||
acc_bits += 8;
|
||||
|
||||
// When we have bit_len or more bits in the accumulator, write the next
|
||||
// output element.
|
||||
if acc_bits >= bit_len {
|
||||
acc_bits -= bit_len;
|
||||
for x in 0usize..byte_pad {
|
||||
array.push(0);
|
||||
}
|
||||
for x in byte_pad..out_width {
|
||||
array.push((
|
||||
// Big-endian
|
||||
(acc_value >> (acc_bits + (8 * (out_width - x - 1)))) as u8
|
||||
) & (
|
||||
// Apply bit_len_mask across byte boundaries
|
||||
((bit_len_mask >> (8 * (out_width - x - 1))) & 0xFF) as u8
|
||||
));
|
||||
}
|
||||
j += out_width;
|
||||
}
|
||||
}
|
||||
|
||||
array
|
||||
}
|
||||
|
||||
fn compress_array(data: &[u8], array: &mut Vec<u8>, bit_len: usize, byte_pad: usize) {
|
||||
let in_width = (bit_len + 7) / 8 + byte_pad;
|
||||
let bit_len_mask = (1u32 << bit_len) - 1;
|
||||
|
||||
// The acc_bits least-significant bits of acc_value represent a bit sequence
|
||||
// in big-endian order.
|
||||
let mut acc_bits = 0usize;
|
||||
let mut acc_value = 0u32;
|
||||
|
||||
let mut j = 0usize;
|
||||
for i in 0usize..array.len() {
|
||||
// When we have fewer than 8 bits left in the accumulator, read the next
|
||||
// input element.
|
||||
if acc_bits < 8 {
|
||||
acc_value = acc_value << bit_len;
|
||||
for x in byte_pad..in_width {
|
||||
acc_value = acc_value | ((
|
||||
data[j + x] & (((bit_len_mask >> (8 * (in_width - x - 1))) & 0xFF) as u8)
|
||||
) as u32) << (8 * (in_width - x - 1));
|
||||
}
|
||||
j += in_width;
|
||||
acc_bits += bit_len;
|
||||
}
|
||||
|
||||
acc_bits -= 8;
|
||||
array[i] = ((acc_value >> acc_bits) & 0xFF) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
fn new_blake2(params: &EquihashParams) -> Blake2b {
|
||||
let mut personalization = [0u8; 16];
|
||||
personalization[0..8].clone_from_slice(b"ZcashPoW");
|
||||
personalization[8..12].clone_from_slice(&to_little_endian(params.N));
|
||||
personalization[12..16].clone_from_slice(&to_little_endian(params.K));
|
||||
Blake2b::with_params(params.hash_output(), &[], &[], &personalization)
|
||||
}
|
||||
|
||||
fn to_little_endian(num: u32) -> [u8; 4] {
|
||||
let mut le_num = [0u8; 4];
|
||||
LittleEndian::write_u32(&mut le_num[..], num);
|
||||
le_num
|
||||
}
|
||||
|
||||
fn to_big_endian(num: u32) -> [u8; 4] {
|
||||
let mut be_num = [0u8; 4];
|
||||
BigEndian::write_u32(&mut be_num[..], num);
|
||||
be_num
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn test_equihash_verifier(n: u32, k: u32, input: &[u8], nonce: U256, solution: &[u32]) -> bool {
|
||||
use primitives::bigint::{Uint, U256};
|
||||
use super::*;
|
||||
|
||||
fn test_equihash_verifier(n: u32, k: u32, input: &[u8], nonce: U256, solution: &[u32]) -> bool {
|
||||
let solution = get_minimal_from_indices(solution, (n / (k + 1)) as usize);
|
||||
/*
|
||||
|
||||
ZCash (reset && BOOST_TEST_LOG_LEVEL=message ./src/test/test_bitcoin --run_test=equihash_tests/validator_testvectors):
|
||||
|
||||
|
||||
pbtc:
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
let mut le_nonce = vec![0; 32];
|
||||
nonce.to_little_endian(&mut le_nonce);
|
||||
let mut input = input.to_vec();
|
||||
input.extend(le_nonce);
|
||||
|
||||
let params = EquihashParams { N: n, K: k };
|
||||
|
||||
verify_equihash_solution(¶ms, &input, &solution)
|
||||
}
|
||||
void TestEquihashValidator(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, std::vector<uint32_t> soln, bool expected) {
|
||||
|
||||
#[test]
|
||||
fn verify_equihash_solution_works() {
|
||||
test_equihash_verifier(
|
||||
96, 5, "Equihash is an asymmetric PoW based on the Generalised Birthday problem.",
|
||||
U256::one(),
|
||||
);
|
||||
assert!(test_equihash_verifier(
|
||||
96, 5, b"Equihash is an asymmetric PoW based on the Generalised Birthday problem.",
|
||||
U256::one(), &vec![
|
||||
2261, 15185, 36112, 104243, 23779, 118390, 118332, 130041, 32642, 69878, 76925, 80080, 45858, 116805, 92842, 111026, 15972, 115059, 85191, 90330, 68190, 122819, 81830, 91132, 23460, 49807, 52426, 80391, 69567, 114474, 104973, 122568,
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ extern crate log;
|
|||
extern crate parking_lot;
|
||||
extern crate rayon;
|
||||
extern crate blake2_rfc;
|
||||
extern crate byteorder;
|
||||
|
||||
extern crate storage;
|
||||
extern crate chain;
|
||||
|
@ -74,6 +75,7 @@ pub mod constants;
|
|||
mod canon;
|
||||
mod deployments;
|
||||
mod duplex_store;
|
||||
mod equihash;
|
||||
mod error;
|
||||
mod sigops;
|
||||
mod timestamp;
|
||||
|
|
|
@ -227,6 +227,7 @@ mod tests {
|
|||
time: 1269211443,
|
||||
bits: 0x207fffff.into(),
|
||||
nonce: 0,
|
||||
equihash_solution: None,
|
||||
});
|
||||
|
||||
// create x100 pre-HF blocks
|
||||
|
@ -286,6 +287,7 @@ mod tests {
|
|||
time: 1269211443,
|
||||
bits: initial_bits.into(),
|
||||
nonce: 0,
|
||||
equihash_solution: None,
|
||||
});
|
||||
|
||||
// Pile up some blocks every 10 mins to establish some history.
|
||||
|
|
Loading…
Reference in New Issue