equihash working
This commit is contained in:
parent
4365a54099
commit
70a8770f13
|
@ -61,7 +61,7 @@ name = "base64"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ dependencies = [
|
||||||
name = "bencher"
|
name = "bencher"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
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",
|
"chain 0.1.0",
|
||||||
"db 0.1.0",
|
"db 0.1.0",
|
||||||
"network 0.1.0",
|
"network 0.1.0",
|
||||||
|
@ -85,7 +85,7 @@ name = "bigint"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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)",
|
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -121,9 +121,19 @@ name = "bitflags"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.1.0"
|
version = "1.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -131,7 +141,7 @@ name = "bytes"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -217,7 +232,7 @@ name = "csv"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -255,7 +270,7 @@ name = "domain"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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)",
|
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -614,7 +629,7 @@ name = "message"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcrypto 0.1.0",
|
"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",
|
"chain 0.1.0",
|
||||||
"network 0.1.0",
|
"network 0.1.0",
|
||||||
"primitives 0.1.0",
|
"primitives 0.1.0",
|
||||||
|
@ -635,7 +650,7 @@ name = "miner"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcrypto 0.1.0",
|
"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",
|
"chain 0.1.0",
|
||||||
"db 0.1.0",
|
"db 0.1.0",
|
||||||
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -683,7 +698,7 @@ name = "murmur3"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
|
@ -864,7 +879,7 @@ name = "primitives"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bigint 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -1125,7 +1140,7 @@ dependencies = [
|
||||||
name = "serialization"
|
name = "serialization"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
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",
|
"primitives 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1221,7 +1236,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bitcrypto 0.1.0",
|
"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",
|
"chain 0.1.0",
|
||||||
"db 0.1.0",
|
"db 0.1.0",
|
||||||
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1421,6 +1436,8 @@ name = "verification"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcrypto 0.1.0",
|
"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",
|
"chain 0.1.0",
|
||||||
"db 0.1.0",
|
"db 0.1.0",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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.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 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 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 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 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 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 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 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-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-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"
|
"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,
|
nonce: self.nonce,
|
||||||
merkle_root_hash: self.merkle_root,
|
merkle_root_hash: self.merkle_root,
|
||||||
version: self.version,
|
version: self.version,
|
||||||
|
equihash_solution: None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -335,6 +336,7 @@ impl<F> TransactionBuilder<F> where F: Invoke<chain::Transaction> {
|
||||||
version: self.version,
|
version: self.version,
|
||||||
inputs: self.inputs,
|
inputs: self.inputs,
|
||||||
outputs: self.outputs,
|
outputs: self.outputs,
|
||||||
|
joint_split: None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ lazy_static = "1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rayon = "1.0"
|
rayon = "1.0"
|
||||||
parking_lot = "0.4"
|
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" }
|
primitives = { path = "../primitives" }
|
||||||
chain = { path = "../chain" }
|
chain = { path = "../chain" }
|
||||||
serialization = { path = "../serialization" }
|
serialization = { path = "../serialization" }
|
||||||
|
|
|
@ -506,6 +506,7 @@ mod tests {
|
||||||
.into_bytes(),
|
.into_bytes(),
|
||||||
}],
|
}],
|
||||||
lock_time: 0xffffffff,
|
lock_time: 0xffffffff,
|
||||||
|
joint_split: None,
|
||||||
}.into();
|
}.into();
|
||||||
|
|
||||||
assert_eq!(transaction.raw.outputs[0].script_pubkey.len(), 46 + 2);
|
assert_eq!(transaction.raw.outputs[0].script_pubkey.len(), 46 + 2);
|
||||||
|
|
|
@ -294,6 +294,7 @@ mod tests {
|
||||||
time: time,
|
time: time,
|
||||||
bits: 0.into(),
|
bits: 0.into(),
|
||||||
nonce: height,
|
nonce: height,
|
||||||
|
equihash_solution: None,
|
||||||
};
|
};
|
||||||
previous_header_hash = header.hash();
|
previous_header_hash = header.hash();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// https://github.com/zcash/zcash/commit/fdda3c5085199d2c2170887aa064fc42afdb0360
|
// https://github.com/zcash/zcash/commit/fdda3c5085199d2c2170887aa064fc42afdb0360
|
||||||
|
|
||||||
use blake2_rfc::blake2b::Blake2b;
|
use blake2_rfc::blake2b::Blake2b;
|
||||||
|
use byteorder::{BigEndian, LittleEndian, ByteOrder, WriteBytesExt};
|
||||||
|
use primitives::hex::ToHex;
|
||||||
|
|
||||||
pub struct EquihashParams {
|
pub struct EquihashParams {
|
||||||
pub N: u32,
|
pub N: u32,
|
||||||
|
@ -8,12 +10,32 @@ pub struct EquihashParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
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 {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut context = Blake2b::new(64);
|
let mut context = new_blake2(params);
|
||||||
context.update(input);
|
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> {
|
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 indices_len = 8 * 4 * solution.len() / (collision_bit_length + 1);
|
||||||
let byte_pad = 4 - ((collision_bit_length + 1 + 7) / 8);
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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]
|
#[test]
|
||||||
fn verify_equihash_solution_works() {
|
fn verify_equihash_solution_works() {
|
||||||
test_equihash_verifier(
|
assert!(test_equihash_verifier(
|
||||||
96, 5, "Equihash is an asymmetric PoW based on the Generalised Birthday problem.",
|
96, 5, b"Equihash is an asymmetric PoW based on the Generalised Birthday problem.",
|
||||||
U256::one(),
|
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 parking_lot;
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
extern crate blake2_rfc;
|
extern crate blake2_rfc;
|
||||||
|
extern crate byteorder;
|
||||||
|
|
||||||
extern crate storage;
|
extern crate storage;
|
||||||
extern crate chain;
|
extern crate chain;
|
||||||
|
@ -74,6 +75,7 @@ pub mod constants;
|
||||||
mod canon;
|
mod canon;
|
||||||
mod deployments;
|
mod deployments;
|
||||||
mod duplex_store;
|
mod duplex_store;
|
||||||
|
mod equihash;
|
||||||
mod error;
|
mod error;
|
||||||
mod sigops;
|
mod sigops;
|
||||||
mod timestamp;
|
mod timestamp;
|
||||||
|
|
|
@ -227,6 +227,7 @@ mod tests {
|
||||||
time: 1269211443,
|
time: 1269211443,
|
||||||
bits: 0x207fffff.into(),
|
bits: 0x207fffff.into(),
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
|
equihash_solution: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// create x100 pre-HF blocks
|
// create x100 pre-HF blocks
|
||||||
|
@ -286,6 +287,7 @@ mod tests {
|
||||||
time: 1269211443,
|
time: 1269211443,
|
||||||
bits: initial_bits.into(),
|
bits: initial_bits.into(),
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
|
equihash_solution: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pile up some blocks every 10 mins to establish some history.
|
// Pile up some blocks every 10 mins to establish some history.
|
||||||
|
|
Loading…
Reference in New Issue