Commits on Source (11)
......@@ -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"
......@@ -262,7 +277,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)",
......@@ -629,7 +644,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",
......@@ -650,7 +665,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)",
......@@ -698,7 +713,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]]
......@@ -720,6 +735,8 @@ dependencies = [
"chain 0.1.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"primitives 0.1.0",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialization 0.1.0",
]
[[package]]
......@@ -864,6 +881,7 @@ dependencies = [
"primitives 0.1.0",
"rpc 0.1.0",
"script 0.1.0",
"serialization 0.1.0",
"storage 0.1.0",
"sync 0.1.0",
"verification 0.1.0",
......@@ -879,7 +897,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-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
......@@ -1145,8 +1163,9 @@ 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",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -1241,7 +1260,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)",
......@@ -1441,6 +1460,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)",
......@@ -1448,6 +1469,7 @@ dependencies = [
"network 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"primitives 0.1.0",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"script 0.1.0",
"serialization 0.1.0",
......@@ -1536,12 +1558,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"
......
......@@ -26,14 +26,13 @@ import = { path = "import" }
logs = { path = "logs" }
rpc = { path = "rpc" }
primitives = { path = "primitives" }
serialization = { path = "serialization" }
[profile.dev]
debug = true
panic = 'abort'
[profile.release]
debug = true
panic = 'abort'
[profile.test]
debug = true
......
This diff is collapsed.
use std::io;
use std::fmt;
use hex::FromHex;
use hex::{ToHex, FromHex};
use ser::{deserialize, serialize};
use crypto::dhash256;
use compact::Compact;
use hash::H256;
use primitives::bytes::Bytes;
use ser::{Error, Serializable, Deserializable, Stream, Reader};
#[derive(PartialEq, Clone, Serializable, Deserializable)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct EquihashSolution(pub Vec<u8>); // TODO: len = 1344
#[derive(PartialEq, Clone)]
pub struct BlockHeader {
pub version: u32,
pub previous_header_hash: H256,
pub merkle_root_hash: H256,
pub time: u32,
pub bits: Compact,
pub nonce: u32,
pub nonce: BlockHeaderNonce,
pub hash_final_sapling_root: Option<H256>,
pub equihash_solution: Option<EquihashSolution>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum BlockHeaderNonce {
U32(u32),
H256(H256),
}
impl From<u32> for BlockHeaderNonce {
fn from(nonce: u32) -> Self {
BlockHeaderNonce::U32(nonce)
}
}
impl BlockHeader {
pub fn hash(&self) -> H256 {
dhash256(&serialize(self))
}
pub fn equihash_input(&self) -> Bytes {
let mut stream = Stream::new();
stream
.append(&self.version)
.append(&self.previous_header_hash)
.append(&self.merkle_root_hash);
if let Some(hash_final_sapling_root) = self.hash_final_sapling_root.as_ref() {
stream.append(hash_final_sapling_root);
}
stream
.append(&self.time)
.append(&self.bits);
match self.nonce {
BlockHeaderNonce::U32(ref v) => stream.append(v),
BlockHeaderNonce::H256(ref v) => stream.append(v),
};
stream.out()
}
}
impl fmt::Debug for BlockHeader {
......@@ -27,9 +70,11 @@ impl fmt::Debug for BlockHeader {
.field("version", &self.version)
.field("previous_header_hash", &self.previous_header_hash.reversed())
.field("merkle_root_hash", &self.merkle_root_hash.reversed())
.field("hash_final_sapling_root", &self.hash_final_sapling_root)
.field("time", &self.time)
.field("bits", &self.bits)
.field("nonce", &self.nonce)
.field("equihash_solution", &self.equihash_solution.as_ref().map(|s| s.0.to_hex::<String>()))
.finish()
}
}
......@@ -40,6 +85,72 @@ impl From<&'static str> for BlockHeader {
}
}
impl Serializable for BlockHeader {
fn serialize(&self, stream: &mut Stream) {
stream
.append(&self.version)
.append(&self.previous_header_hash)
.append(&self.merkle_root_hash);
if let Some(hash_final_sapling_root) = self.hash_final_sapling_root.as_ref() {
stream.append(hash_final_sapling_root);
}
stream
.append(&self.time)
.append(&self.bits);
match self.nonce {
BlockHeaderNonce::U32(ref v) => stream.append(v),
BlockHeaderNonce::H256(ref v) => stream.append(v),
};
if let Some(ref equihash_solution) = self.equihash_solution {
stream.append_list(&equihash_solution.0);
}
}
}
impl Deserializable for BlockHeader {
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, Error> where Self: Sized, T: io::Read {
let is_zcash_format = reader.is_zcash_reader();
let version = reader.read()?;
let previous_header_hash = reader.read()?;
let merkle_root_hash = reader.read()?;
// TODO: rename to transaction format - original, witness, zcash, must be enum, not flags
let hash_final_sapling_root = if is_zcash_format {
Some(reader.read()?)
} else {
None
};
let time = reader.read()?;
let bits = reader.read()?;
let nonce = match is_zcash_format {
true => BlockHeaderNonce::H256(reader.read()?),
false => BlockHeaderNonce::U32(reader.read()?),
};
let equihash_solution = if is_zcash_format {
Some(EquihashSolution(reader.read_list()?))
} else {
None
};
Ok(BlockHeader {
version,
previous_header_hash,
merkle_root_hash,
hash_final_sapling_root,
time,
bits,
nonce,
equihash_solution,
})
}
}
#[cfg(test)]
mod tests {
use ser::{Reader, Error as ReaderError, Stream};
......@@ -53,10 +164,11 @@ mod tests {
merkle_root_hash: [3; 32].into(),
time: 4,
bits: 5.into(),
nonce: 6,
nonce: 6.into(),
equihash_solution: None,
};
let mut stream = Stream::default();
let mut stream = Stream::new();
stream.append(&block_header);
let expected = vec![
......@@ -82,7 +194,7 @@ mod tests {
6, 0, 0, 0,
];
let mut reader = Reader::new(&buffer);
let mut reader = Reader::new(&buffer, 0);
let expected = BlockHeader {
version: 1,
......@@ -90,7 +202,8 @@ mod tests {
merkle_root_hash: [3; 32].into(),
time: 4,
bits: 5.into(),
nonce: 6,
nonce: 6.into(),
equihash_solution: None,
};
assert_eq!(expected, reader.read().unwrap());
......
use std::io;
use hex::{ToHex, FromHex};
use hash::{H256, H512};
use ser::{Error, Serializable, Deserializable, Stream, Reader, FixedArray_H256_2,
FixedArray_u8_296, FixedArray_u8_601_2};
#[derive(Debug, PartialEq, Default, Clone)]
pub struct JointSplit {
pub descriptions: Vec<JointSplitDescription>,
pub pubkey: H256,
pub sig: H512,
}
#[derive(Debug, PartialEq, Default, Clone, Serializable, Deserializable)]
pub struct JointSplitDescription {
pub value_pub_old: u64,
pub value_pub_new: u64,
pub anchor: H256,
pub nullifiers: FixedArray_H256_2,
pub commitments: FixedArray_H256_2,
pub ephemeral_key: H256,
pub random_seed: H256,
pub macs: FixedArray_H256_2,
pub zkproof: FixedArray_u8_296,
pub ciphertexts: FixedArray_u8_601_2,
}
pub fn serialize_joint_split(stream: &mut Stream, joint_split: &Option<JointSplit>) {
if let &Some(ref joint_split) = joint_split {
stream.append_list(&joint_split.descriptions)
.append(&joint_split.pubkey)
.append(&joint_split.sig);
}
}
pub fn deserialize_joint_split<T>(reader: &mut Reader<T>) -> Result<Option<JointSplit>, Error> where T: io::Read {
let descriptions: Vec<JointSplitDescription> = reader.read_list()?;
if descriptions.is_empty() {
return Ok(None);
}
let pubkey = reader.read()?;
let sig = reader.read()?;
Ok(Some(JointSplit {
descriptions,
pubkey,
sig,
}))
}
......@@ -10,6 +10,7 @@ pub mod constants;
mod block;
mod block_header;
mod join_split;
mod merkle_root;
mod transaction;
......@@ -26,7 +27,8 @@ pub trait RepresentH256 {
pub use primitives::{hash, bytes, bigint, compact};
pub use block::Block;
pub use block_header::BlockHeader;
pub use block_header::{BlockHeader, BlockHeaderNonce};
pub use join_split::{JointSplit, JointSplitDescription};
pub use merkle_root::{merkle_root, merkle_node_hash};
pub use transaction::{Transaction, TransactionInput, TransactionOutput, OutPoint};
......
......@@ -9,6 +9,7 @@ use ser::{deserialize, serialize, serialize_with_flags, SERIALIZE_TRANSACTION_WI
use crypto::dhash256;
use hash::H256;
use constants::{SEQUENCE_FINAL, LOCKTIME_THRESHOLD};
use join_split::{JointSplit, deserialize_joint_split, serialize_joint_split};
use ser::{Error, Serializable, Deserializable, Stream, Reader};
/// Must be zero.
......@@ -96,6 +97,7 @@ pub struct Transaction {
pub inputs: Vec<TransactionInput>,
pub outputs: Vec<TransactionOutput>,
pub lock_time: u32,
pub joint_split: Option<JointSplit>,
}
impl From<&'static str> for Transaction {
......@@ -205,6 +207,16 @@ impl Deserializable for TransactionInput {
impl Serializable for Transaction {
fn serialize(&self, stream: &mut Stream) {
if stream.is_zcash_stream() {
stream
.append(&self.version)
.append_list(&self.inputs)
.append_list(&self.outputs)
.append(&self.lock_time);
serialize_joint_split(stream, &self.joint_split);
return;
}
let include_transaction_witness = stream.include_transaction_witness() && self.has_witness();
match include_transaction_witness {
false => stream
......@@ -232,7 +244,8 @@ impl Deserializable for Transaction {
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, Error> where Self: Sized, T: io::Read {
let version = reader.read()?;
let mut inputs: Vec<TransactionInput> = reader.read_list()?;
let read_witness = if inputs.is_empty() {
// TODO: default flags must be: ZCASH, WITNESS, ...
let read_witness = if inputs.is_empty() && !reader.is_zcash_reader() {
let witness_flag: u8 = reader.read()?;
if witness_flag != WITNESS_FLAG {
return Err(Error::MalformedData);
......@@ -249,12 +262,19 @@ impl Deserializable for Transaction {
input.script_witness = reader.read_list()?;
}
}
let lock_time = reader.read()?;
let joint_split = if version >= 2 && reader.is_zcash_reader() {
deserialize_joint_split(reader)?
} else {
None
};
Ok(Transaction {
version: version,
inputs: inputs,
outputs: outputs,
lock_time: reader.read()?,
lock_time: lock_time,
joint_split: joint_split,
})
}
}
......@@ -332,6 +352,7 @@ mod tests {
script_pubkey: "76a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac".into(),
}],
lock_time: 0x00000011,
joint_split: None,
};
assert_eq!(actual, expected);
}
......
......@@ -2,7 +2,7 @@ use ser::Stream;
use bytes::{TaggedBytes, Bytes};
use network::Magic;
use common::Command;
use serialization::serialize_payload_with_flags;
use serialization::serialize_payload;
use {Payload, MessageResult, MessageHeader};
pub fn to_raw_message(magic: Magic, command: Command, payload: &Bytes) -> Bytes {
......@@ -22,8 +22,8 @@ impl<T> Message<T> where T: Payload {
Self::with_flags(magic, version, payload, 0)
}
pub fn with_flags(magic: Magic, version: u32, payload: &T, serialization_flags: u32) -> MessageResult<Self> {
let serialized = try!(serialize_payload_with_flags(payload, version, serialization_flags));
pub fn with_flags(magic: Magic, version: u32, payload: &T, flags: u32) -> MessageResult<Self> {
let serialized = try!(serialize_payload(payload, version, flags));
let message = Message {
bytes: TaggedBytes::new(to_raw_message(magic, T::command().into(), &serialized)),
......
......@@ -25,12 +25,12 @@ impl MessageHeader {
}
impl MessageHeader {
pub fn deserialize(data: &[u8], expected: Magic) -> Result<Self, Error> {
pub fn deserialize(data: &[u8], flags: u32, expected: Magic) -> Result<Self, Error> {
if data.len() != 24 {
return Err(Error::Deserialize);
}
let mut reader = Reader::new(data);
let mut reader = Reader::new(data, flags);
let magic: u32 = try!(reader.read());
let magic = Magic::from(magic);
if expected != magic {
......@@ -88,6 +88,6 @@ mod tests {
checksum: "ed52399b".into(),
};
assert_eq!(expected, MessageHeader::deserialize(&raw, Network::Mainnet.magic(&ConsensusFork::BitcoinCore)).unwrap());
assert_eq!(expected, MessageHeader::deserialize(&raw, 0, Network::Mainnet.magic(&ConsensusFork::BitcoinCore)).unwrap());
}
}
mod stream;
mod reader;
pub use self::stream::{serialize_payload, serialize_payload_with_flags};
pub use self::stream::serialize_payload;
pub use self::reader::deserialize_payload;
use ser::Reader;
use {Payload, Error};
pub fn deserialize_payload<T>(buffer: &[u8], version: u32) -> Result<T, Error> where T: Payload {
let mut reader = PayloadReader::new(buffer, version);
pub fn deserialize_payload<T>(buffer: &[u8], version: u32, flags: u32) -> Result<T, Error> where T: Payload {
let mut reader = PayloadReader::new(buffer, version, flags);
let result = try!(reader.read());
if !reader.is_finished() {
return Err(Error::Deserialize);
......@@ -17,9 +17,9 @@ pub struct PayloadReader<T> {
}
impl<'a> PayloadReader<&'a [u8]> {
pub fn new(buffer: &'a [u8], version: u32) -> Self {
pub fn new(buffer: &'a [u8], version: u32, flags: u32) -> Self {
PayloadReader {
reader: Reader::new(buffer),
reader: Reader::new(buffer, flags),
version: version,
}
}
......
......@@ -2,12 +2,8 @@ use bytes::Bytes;
use ser::Stream;
use {Payload, Error, MessageResult};
pub fn serialize_payload<T>(t: &T, version: u32) -> MessageResult<Bytes> where T: Payload {
serialize_payload_with_flags(t, version, 0)
}
pub fn serialize_payload_with_flags<T>(t: &T, version: u32, serialization_flags: u32) -> MessageResult<Bytes> where T: Payload {
let mut stream = PayloadStream::new(version, serialization_flags);
pub fn serialize_payload<T>(t: &T, version: u32, flags: u32) -> MessageResult<Bytes> where T: Payload {
let mut stream = PayloadStream::new(version, flags);
try!(stream.append(t));
Ok(stream.out())
}
......@@ -18,9 +14,9 @@ pub struct PayloadStream {
}
impl PayloadStream {
pub fn new(version: u32, serialization_flags: u32) -> Self {
pub fn new(version: u32, flags: u32) -> Self {
PayloadStream {
stream: Stream::with_flags(serialization_flags),
stream: Stream::with_flags(flags),
version: version,
}
}
......
......@@ -196,7 +196,7 @@ impl Deserializable for V70001 {
impl From<&'static str> for Version {
fn from(s: &'static str) -> Self {
let bytes: Bytes = s.into();
deserialize_payload(&bytes, 0).unwrap()
deserialize_payload(&bytes, 0, 0).unwrap()
}
}
......@@ -222,7 +222,7 @@ mod test {
start_height: 98645,
});
assert_eq!(serialize_payload(&version, 0), Ok(expected));
assert_eq!(serialize_payload(&version, 0, 0), Ok(expected));
}
#[test]
......@@ -241,6 +241,6 @@ mod test {
start_height: 98645,
});
assert_eq!(expected, deserialize_payload(&raw, 0).unwrap());
assert_eq!(expected, deserialize_payload(&raw, 0, 0).unwrap());
}
}
......@@ -161,6 +161,7 @@ mod tests {
script_pubkey: script_pubkey,
}],
lock_time: 0,
joint_split: None,
};
P2shCoinbaseTransactionBuilder {
......
......@@ -7,3 +7,5 @@ authors = ["debris <[email protected]>"]
lazy_static = "1.0"
chain = { path = "../chain" }
primitives = { path = "../primitives" }
serialization = { path = "../serialization" }
rustc-hex = "2"
......@@ -46,6 +46,15 @@ pub struct BitcoinCashConsensusParams {
pub magnetic_anomaly_time: u32,
}
#[derive(Debug, Clone)]
/// ZCash consensus parameters.
pub struct ZCashConsensusParams {
pub pow_averaging_window: u32,
pub pow_max_adjust_down: u32,
pub pow_max_adjust_up: u32,
pub pow_target_spacing: u32,
}
#[derive(Debug, Clone)]
/// Concurrent consensus rule forks.
pub enum ConsensusFork {
......@@ -58,6 +67,8 @@ pub enum ConsensusFork {
/// UAHF Technical Specification - https://github.com/Bitcoin-UAHF/spec/blob/master/uahf-technical-spec.md
/// BUIP-HF Digest for replay protected signature verification across hard forks - https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md
BitcoinCash(BitcoinCashConsensusParams),
/// ZCash.
ZCash(ZCashConsensusParams),
}
#[derive(Debug, Clone, Copy)]
......@@ -76,10 +87,22 @@ impl ConsensusParams {
match network {
Network::Mainnet | Network::Other(_) => ConsensusParams {
network: network,
bip16_time: 1333238400, // Apr 1 2012
bip34_height: 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8
bip65_height: 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
bip66_height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
bip16_time: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 1333238400, // Apr 1 2012
},
bip34_height: match fork {
ConsensusFork::ZCash(_) => 1,
_ => 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8
},
bip65_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
},
bip66_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
},
segwit_deployment: match fork {
ConsensusFork::BitcoinCore => Some(Deployment {
name: "segwit",
......@@ -88,7 +111,7 @@ impl ConsensusParams {
timeout: 1510704000,
activation: Some(481824),
}),
ConsensusFork::BitcoinCash(_) => None,
ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) => None,
},
fork: fork,
rule_change_activation_threshold: 1916, // 95%
......@@ -103,10 +126,22 @@ impl ConsensusParams {
},
Network::Testnet => ConsensusParams {
network: network,
bip16_time: 1333238400, // Apr 1 2012
bip34_height: 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
bip65_height: 581885, // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
bip66_height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
bip16_time: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 1333238400, // Apr 1 2012
},
bip34_height: match fork {
ConsensusFork::ZCash(_) => 1,
_ => 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
},
bip65_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 581885, // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
},
bip66_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
},
segwit_deployment: match fork {
ConsensusFork::BitcoinCore => Some(Deployment {
name: "segwit",
......@@ -115,7 +150,7 @@ impl ConsensusParams {
timeout: 1493596800,
activation: Some(834624),
}),
ConsensusFork::BitcoinCash(_) => None,
ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) => None,
},
fork: fork,
rule_change_activation_threshold: 1512, // 75%
......@@ -130,10 +165,22 @@ impl ConsensusParams {
},
Network::Regtest | Network::Unitest => ConsensusParams {
network: network,
bip16_time: 1333238400, // Apr 1 2012
bip34_height: 100000000, // not activated on regtest
bip65_height: 1351,
bip66_height: 1251, // used only in rpc tests
bip16_time: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 1333238400, // Apr 1 2012
},
bip34_height: match fork {
ConsensusFork::ZCash(_) => 1,
_ => 100000000, // not activated on regtest
},
bip65_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 1351,
},
bip66_height: match fork {
ConsensusFork::ZCash(_) => 0,
_ => 1251, // used only in rpc tests
},
segwit_deployment: match fork {
ConsensusFork::BitcoinCore => Some(Deployment {
name: "segwit",
......@@ -142,7 +189,7 @@ impl ConsensusParams {
timeout: ::std::u32::MAX,
activation: None,
}),
ConsensusFork::BitcoinCash(_) => None,
ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) => None,
},
fork: fork,
rule_change_activation_threshold: 108, // 75%
......@@ -172,7 +219,7 @@ impl ConsensusParams {
match self.fork {
// SegWit is not supported in (our?) regtests
ConsensusFork::BitcoinCore if self.network != Network::Regtest => true,
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) => false,
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) => false,
}
}
}
......@@ -197,6 +244,7 @@ impl ConsensusFork {
match *self {
ConsensusFork::BitcoinCore => 0,
ConsensusFork::BitcoinCash(ref fork) => fork.height,
ConsensusFork::ZCash(_) => 0,
}
}
......@@ -218,6 +266,7 @@ impl ConsensusFork {
// size of first fork block must be larger than 1MB
ConsensusFork::BitcoinCash(ref fork) if height == fork.height => 1_000_001,
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) => 0,
ConsensusFork::ZCash(_) => 0,
}
}
......@@ -226,6 +275,7 @@ impl ConsensusFork {
ConsensusFork::BitcoinCash(ref fork) if median_time_past >= fork.monolith_time => 32_000_000,
ConsensusFork::BitcoinCash(ref fork) if height >= fork.height => 8_000_000,
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) => 1_000_000,
ConsensusFork::ZCash(_) => 2_000_000,
}
}
......@@ -234,13 +284,13 @@ impl ConsensusFork {
// according to REQ-5: max_block_sigops = 20000 * ceil((max(blocksize_bytes, 1000000) / 1000000))
ConsensusFork::BitcoinCash(ref fork) if height >= fork.height =>
20_000 * (1 + (block_size - 1) / 1_000_000),
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) => 20_000,
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) => 20_000,
}
}
pub fn max_block_sigops_cost(&self, height: u32, block_size: usize) -> usize {
match *self {
ConsensusFork::BitcoinCash(_) =>
ConsensusFork::BitcoinCash(_) | ConsensusFork::ZCash(_) =>
self.max_block_sigops(height, block_size) * Self::witness_scale_factor(),
ConsensusFork::BitcoinCore =>
80_000,
......@@ -249,7 +299,7 @@ impl ConsensusFork {
pub fn max_block_weight(&self, _height: u32) -> usize {
match *self {
ConsensusFork::BitcoinCore =>
ConsensusFork::BitcoinCore | ConsensusFork::ZCash(_) =>
4_000_000,
ConsensusFork::BitcoinCash(_) =>
unreachable!("BitcoinCash has no SegWit; weight is only checked with SegWit activated; qed"),
......@@ -290,6 +340,43 @@ impl BitcoinCashConsensusParams {
}
}
impl ZCashConsensusParams {
pub fn new(network: Network) -> Self {
match network {
Network::Mainnet | Network::Other(_) => ZCashConsensusParams {
pow_averaging_window: 17,
pow_max_adjust_down: 32,
pow_max_adjust_up: 16,
pow_target_spacing: (2.5 * 60.0) as u32,
},
Network::Testnet => ZCashConsensusParams {
pow_averaging_window: 17,
pow_max_adjust_down: 32,
pow_max_adjust_up: 16,
pow_target_spacing: (2.5 * 60.0) as u32,
},
Network::Regtest | Network::Unitest => ZCashConsensusParams {
pow_averaging_window: 17,
pow_max_adjust_down: 0,
pow_max_adjust_up: 0,
pow_target_spacing: (2.5 * 60.0) as u32,
},
}
}
pub fn averaging_window_timespan(&self) -> u32 {
self.pow_averaging_window * self.pow_target_spacing
}
pub fn min_actual_timespan(&self) -> u32 {
(self.averaging_window_timespan() * (100 - self.pow_max_adjust_up)) / 100
}
pub fn max_actual_timespan(&self) -> u32 {
(self.averaging_window_timespan() * (100 + self.pow_max_adjust_down)) / 100
}
}
#[cfg(test)]
mod tests {
use super::super::Network;
......
......@@ -3,6 +3,8 @@ extern crate lazy_static;
extern crate chain;
extern crate primitives;
extern crate serialization;
extern crate rustc_hex as hex;
mod consensus;
mod deployments;
......@@ -10,6 +12,6 @@ mod network;
pub use primitives::{hash, compact};
pub use consensus::{ConsensusParams, ConsensusFork, BitcoinCashConsensusParams, TransactionOrdering};
pub use consensus::{ConsensusParams, ConsensusFork, BitcoinCashConsensusParams, ZCashConsensusParams, TransactionOrdering};
pub use deployments::Deployment;
pub use network::{Magic, Network};
......@@ -16,6 +16,10 @@ const BITCOIN_CASH_MAGIC_MAINNET: u32 = 0xE8F3E1E3;
const BITCOIN_CASH_MAGIC_TESTNET: u32 = 0xF4F3E5F4;
const BITCOIN_CASH_MAGIC_REGTEST: u32 = 0xFABFB5DA;
const ZCASH_MAGIC_MAINNET: u32 = 0x6427e924;
const ZCASH_MAGIC_TESTNET: u32 = 0xbff91afa;
const ZCASH_MAGIC_REGTEST: u32 = 0x5f3fe8aa;
lazy_static! {
static ref MAX_BITS_MAINNET: U256 = "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff".parse()
.expect("hardcoded value should parse without errors");
......@@ -23,6 +27,13 @@ lazy_static! {
.expect("hardcoded value should parse without errors");
static ref MAX_BITS_REGTEST: U256 = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".parse()
.expect("hardcoded value should parse without errors");
static ref ZCASH_MAX_BITS_MAINNET: U256 = "0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".parse()
.expect("hardcoded value should parse without errors");
static ref ZCASH_MAX_BITS_TESTNET: U256 = "07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".parse()
.expect("hardcoded value should parse without errors");
static ref ZCASH_MAX_BITS_REGTEST: U256 = "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f".parse()
.expect("hardcoded value should parse without errors");
}
/// Network magic type.
......@@ -49,6 +60,9 @@ impl Network {
(&ConsensusFork::BitcoinCash(_), Network::Mainnet) => BITCOIN_CASH_MAGIC_MAINNET,
(&ConsensusFork::BitcoinCash(_), Network::Testnet) => BITCOIN_CASH_MAGIC_TESTNET,
(&ConsensusFork::BitcoinCash(_), Network::Regtest) => BITCOIN_CASH_MAGIC_REGTEST,
(&ConsensusFork::ZCash(_), Network::Mainnet) => ZCASH_MAGIC_MAINNET,
(&ConsensusFork::ZCash(_), Network::Testnet) => ZCASH_MAGIC_TESTNET,
(&ConsensusFork::ZCash(_), Network::Regtest) => ZCASH_MAGIC_REGTEST,
(_, Network::Mainnet) => MAGIC_MAINNET,
(_, Network::Testnet) => MAGIC_TESTNET,
(_, Network::Regtest) => MAGIC_REGTEST,
......@@ -57,20 +71,26 @@ impl Network {
}
}
pub fn max_bits(&self) -> U256 {
match *self {
Network::Mainnet | Network::Other(_) => MAX_BITS_MAINNET.clone(),
Network::Testnet => MAX_BITS_TESTNET.clone(),
Network::Regtest => MAX_BITS_REGTEST.clone(),
Network::Unitest => Compact::max_value().into(),
pub fn max_bits(&self, fork: &ConsensusFork) -> U256 {
match (fork, *self) {
(&ConsensusFork::ZCash(_), Network::Mainnet) => ZCASH_MAX_BITS_MAINNET.clone(),
(&ConsensusFork::ZCash(_), Network::Testnet) => ZCASH_MAX_BITS_TESTNET.clone(),
(&ConsensusFork::ZCash(_), Network::Testnet) => ZCASH_MAX_BITS_REGTEST.clone(),
(_, Network::Mainnet) | (_, Network::Other(_)) => MAX_BITS_MAINNET.clone(),
(_, Network::Testnet) => MAX_BITS_TESTNET.clone(),
(_, Network::Regtest) => MAX_BITS_REGTEST.clone(),
(_, Network::Unitest) => Compact::max_value().into(),
}
}
pub fn port(&self) -> u16 {
match *self {
Network::Mainnet | Network::Other(_) => 8333,
Network::Testnet => 18333,
Network::Regtest | Network::Unitest => 18444,
pub fn port(&self, fork: &ConsensusFork) -> u16 {
match (fork, *self) {
(&ConsensusFork::ZCash(_), Network::Mainnet) | (&ConsensusFork::ZCash(_), Network::Other(_)) => 8233,
(&ConsensusFork::ZCash(_), Network::Testnet) => 18233,
(&ConsensusFork::ZCash(_), Network::Regtest) | (&ConsensusFork::ZCash(_), Network::Unitest) => 18344,
(_, Network::Mainnet) | (_, Network::Other(_)) => 8333,
(_, Network::Testnet) => 18333,
(_, Network::Regtest) | (_, Network::Unitest) => 18444,
}
}
......@@ -82,19 +102,34 @@ impl Network {
}
}
pub fn genesis_block(&self) -> Block {
match *self {
Network::Mainnet | Network::Other(_) => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
Network::Testnet => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
Network::Regtest | Network::Unitest => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
pub fn genesis_block(&self, fork: &ConsensusFork) -> Block {
match (fork, *self) {
// TODO
(&ConsensusFork::ZCash(_), Network::Mainnet) | (&ConsensusFork::ZCash(_), Network::Other(_)) => {
use serialization;
use chain;
use hex::FromHex;
let origin = "040000000000000000000000000000000000000000000000000000000000000000000000db4d7a85b768123f1dff1d4c4cece70083b2d27e117b4ac2e31d087988a5eac4000000000000000000000000000000000000000000000000000000000000000090041358ffff071f5712000000000000000000000000000000000000000000000000000000000000fd4005000a889f00854b8665cd555f4656f68179d31ccadc1b1f7fb0952726313b16941da348284d67add4686121d4e3d930160c1348d8191c25f12b267a6a9c131b5031cbf8af1f79c9d513076a216ec87ed045fa966e01214ed83ca02dc1797270a454720d3206ac7d931a0a680c5c5e099057592570ca9bdf6058343958b31901fce1a15a4f38fd347750912e14004c73dfe588b903b6c03166582eeaf30529b14072a7b3079e3a684601b9b3024054201f7440b0ee9eb1a7120ff43f713735494aa27b1f8bab60d7f398bca14f6abb2adbf29b04099121438a7974b078a11635b594e9170f1086140b4173822dd697894483e1c6b4e8b8dcd5cb12ca4903bc61e108871d4d915a9093c18ac9b02b6716ce1013ca2c1174e319c1a570215bc9ab5f7564765f7be20524dc3fdf8aa356fd94d445e05ab165ad8bb4a0db096c097618c81098f91443c719416d39837af6de85015dca0de89462b1d8386758b2cf8a99e00953b308032ae44c35e05eb71842922eb69797f68813b59caf266cb6c213569ae3280505421a7e3a0a37fdf8e2ea354fc5422816655394a9454bac542a9298f176e211020d63dee6852c40de02267e2fc9d5e1ff2ad9309506f02a1a71a0501b16d0d36f70cdfd8de78116c0c506ee0b8ddfdeb561acadf31746b5a9dd32c21930884397fb1682164cb565cc14e089d66635a32618f7eb05fe05082b8a3fae620571660a6b89886eac53dec109d7cbb6930ca698a168f301a950be152da1be2b9e07516995e20baceebecb5579d7cdbc16d09f3a50cb3c7dffe33f26686d4ff3f8946ee6475e98cf7b3cf9062b6966e838f865ff3de5fb064a37a21da7bb8dfd2501a29e184f207caaba364f36f2329a77515dcb710e29ffbf73e2bbd773fab1f9a6b005567affff605c132e4e4dd69f36bd201005458cfbd2c658701eb2a700251cefd886b1e674ae816d3f719bac64be649c172ba27a4fd55947d95d53ba4cbc73de97b8af5ed4840b659370c556e7376457f51e5ebb66018849923db82c1c9a819f173cccdb8f3324b239609a300018d0fb094adf5bd7cbb3834c69e6d0b3798065c525b20f040e965e1a161af78ff7561cd874f5f1b75aa0bc77f720589e1b810f831eac5073e6dd46d00a2793f70f7427f0f798f2f53a67e615e65d356e66fe40609a958a05edb4c175bcc383ea0530e67ddbe479a898943c6e3074c6fcc252d6014de3a3d292b03f0d88d312fe221be7be7e3c59d07fa0f2f4029e364f1f355c5d01fa53770d0cd76d82bf7e60f6903bc1beb772e6fde4a70be51d9c7e03c8d6d8dfb361a234ba47c470fe630820bbd920715621b9fbedb49fcee165ead0875e6c2b1af16f50b5d6140cc981122fcbcf7c5a4e3772b3661b628e08380abc545957e59f634705b1bbde2f0b4e055a5ec5676d859be77e20962b645e051a880fddb0180b4555789e1f9344a436a84dc5579e2553f1e5fb0a599c137be36cabbed0319831fea3fddf94ddc7971e4bcf02cdc93294a9aab3e3b13e3b058235b4f4ec06ba4ceaa49d675b4ba80716f3bc6976b1fbf9c8bf1f3e3a4dc1cd83ef9cf816667fb94f1e923ff63fef072e6a19321e4812f96cb0ffa864da50ad74deb76917a336f31dce03ed5f0303aad5e6a83634f9fcc371096f8288b8f02ddded5ff1bb9d49331e4a84dbe1543164438fde9ad71dab024779dcdde0b6602b5ae0a6265c14b94edd83b37403f4b78fcd2ed555b596402c28ee81d87a909c4e8722b30c71ecdd861b05f61f8b1231795c76adba2fdefa451b283a5d527955b9f3de1b9828e7b2e74123dd47062ddcc09b05e7fa13cb2212a6fdbc65d7e852cec463ec6fd929f5b8483cf3052113b13dac91b69f49d1b7d1aec01c4a68e41ce1570101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff071f0104455a6361736830623963346565663862376363343137656535303031653335303039383462366665613335363833613763616331343161303433633432303634383335643334ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000";
let origin = origin.from_hex::<Vec<u8>>().unwrap();
let genesis: chain::Block = serialization::deserialize_with_flags(&origin as &[u8], serialization::DESERIALIZE_ZCASH).unwrap();
genesis
},
(&ConsensusFork::ZCash(_), Network::Testnet) =>
"".into(),
(&ConsensusFork::ZCash(_), Network::Regtest) | (&ConsensusFork::ZCash(_), Network::Unitest) =>
"".into(),
(_, Network::Mainnet) | (_, Network::Other(_)) => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
(_, Network::Testnet) => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
(_, Network::Regtest) | (_, Network::Unitest) => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(),
}
}
pub fn default_verification_edge(&self) -> H256 {
pub fn default_verification_edge(&self, fork: &ConsensusFork) -> H256 {
match *self {
Network::Mainnet => H256::from_reversed_str("0000000000000000030abc968e1bd635736e880b946085c93152969b9a81a6e2"),
Network::Testnet => H256::from_reversed_str("000000000871ee6842d3648317ccc8a435eb8cc3c2429aee94faff9ba26b05a0"),
_ => self.genesis_block().hash(),
_ => self.genesis_block(fork).hash(),
}
}
}
......@@ -118,18 +153,18 @@ mod tests {
#[test]
fn test_network_max_bits() {
assert_eq!(Network::Mainnet.max_bits(), *MAX_BITS_MAINNET);
assert_eq!(Network::Testnet.max_bits(), *MAX_BITS_TESTNET);
assert_eq!(Network::Regtest.max_bits(), *MAX_BITS_REGTEST);
assert_eq!(Network::Unitest.max_bits(), Compact::max_value().into());
assert_eq!(Network::Mainnet.max_bits(&ConsensusFork::BitcoinCore), *MAX_BITS_MAINNET);
assert_eq!(Network::Testnet.max_bits(&ConsensusFork::BitcoinCore), *MAX_BITS_TESTNET);
assert_eq!(Network::Regtest.max_bits(&ConsensusFork::BitcoinCore), *MAX_BITS_REGTEST);
assert_eq!(Network::Unitest.max_bits(&ConsensusFork::BitcoinCore), Compact::max_value().into());
}
#[test]
fn test_network_port() {
assert_eq!(Network::Mainnet.port(), 8333);
assert_eq!(Network::Testnet.port(), 18333);
assert_eq!(Network::Regtest.port(), 18444);
assert_eq!(Network::Unitest.port(), 18444);
assert_eq!(Network::Mainnet.port(&ConsensusFork::BitcoinCore), 8333);
assert_eq!(Network::Testnet.port(&ConsensusFork::BitcoinCore), 18333);
assert_eq!(Network::Regtest.port(&ConsensusFork::BitcoinCore), 18444);
assert_eq!(Network::Unitest.port(&ConsensusFork::BitcoinCore), 18444);
}
#[test]
......
......@@ -23,4 +23,6 @@ pub struct Config {
pub preferable_services: Services,
/// Internet protocol.
pub internet_protocol: InternetProtocol,
/// Serialization flags.
pub serialization_flags: u32,
}
......@@ -6,26 +6,28 @@ use message::types::{Version, Verack};
use network::Magic;
use io::{write_message, WriteMessage, ReadMessage, read_message};
pub fn handshake<A>(a: A, magic: Magic, version: Version, min_version: u32) -> Handshake<A> where A: AsyncWrite + AsyncRead {
pub fn handshake<A>(a: A, flags: u32, magic: Magic, version: Version, min_version: u32) -> Handshake<A> where A: AsyncWrite + AsyncRead {
Handshake {
version: version.version(),
nonce: version.nonce(),
state: HandshakeState::SendVersion(write_message(a, version_message(magic, version))),
magic: magic,
min_version: min_version,
flags: flags,
}
}
pub fn accept_handshake<A>(a: A, magic: Magic, version: Version, min_version: u32) -> AcceptHandshake<A> where A: AsyncWrite + AsyncRead {
pub fn accept_handshake<A>(a: A, flags: u32, magic: Magic, version: Version, min_version: u32) -> AcceptHandshake<A> where A: AsyncWrite + AsyncRead {
AcceptHandshake {
version: version.version(),
nonce: version.nonce(),
state: AcceptHandshakeState::ReceiveVersion {
local_version: Some(version),
future: read_message(a, magic, 0),
future: read_message(a, flags, magic, 0),
},
magic: magic,
min_version: min_version,
flags: flags,
}
}
......@@ -81,6 +83,7 @@ pub struct Handshake<A> {
version: u32,
nonce: Option<u64>,
min_version: u32,
flags: u32,
}
pub struct AcceptHandshake<A> {
......@@ -89,6 +92,7 @@ pub struct AcceptHandshake<A> {
version: u32,
nonce: Option<u64>,
min_version: u32,
flags: u32,
}
impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
......@@ -100,7 +104,7 @@ impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
let next_state = match self.state {
HandshakeState::SendVersion(ref mut future) => {
let (stream, _) = try_ready!(future.poll());
HandshakeState::ReceiveVersion(read_message(stream, self.magic, 0))
HandshakeState::ReceiveVersion(read_message(stream, self.flags, self.magic, 0))
},
HandshakeState::ReceiveVersion(ref mut future) => {
let (stream, version) = try_ready!(future.poll());
......@@ -125,12 +129,11 @@ impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
},
HandshakeState::SendVerack { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
let version = version.take().expect("verack must be preceded by version");
HandshakeState::ReceiveVerack {
version: Some(version),
future: read_message(stream, self.magic, 0),
future: read_message(stream, self.flags, self.magic, 0),
}
},
HandshakeState::ReceiveVerack { ref mut version, ref mut future } => {
......@@ -310,7 +313,7 @@ mod tests {
write: Bytes::default(),
};
let hs = handshake(test_io, magic, local_version, 0).wait().unwrap();
let hs = handshake(test_io, 0, magic, local_version, 0).wait().unwrap();
assert_eq!(hs.0.write, expected_stream.out());
assert_eq!(hs.1.unwrap(), expected);
}
......@@ -339,7 +342,7 @@ mod tests {
expected_stream.append_slice(Message::new(magic, version, &local_version).unwrap().as_ref());
expected_stream.append_slice(Message::new(magic, version, &Verack).unwrap().as_ref());
let hs = accept_handshake(test_io, magic, local_version, 0).wait().unwrap();
let hs = accept_handshake(test_io, 0, magic, local_version, 0).wait().unwrap();
assert_eq!(hs.0.write, expected_stream.out());
assert_eq!(hs.1.unwrap(), expected);
}
......@@ -361,7 +364,7 @@ mod tests {
let expected = Error::InvalidVersion;
let hs = handshake(test_io, magic, local_version, 0).wait().unwrap();
let hs = handshake(test_io, 0, magic, local_version, 0).wait().unwrap();
assert_eq!(hs.1.unwrap_err(), expected);
}
......@@ -382,7 +385,7 @@ mod tests {
let expected = Error::InvalidVersion;
let hs = accept_handshake(test_io, magic, local_version, 0).wait().unwrap();
let hs = accept_handshake(test_io, 0, magic, local_version, 0).wait().unwrap();
assert_eq!(hs.1.unwrap_err(), expected);
}
......@@ -404,7 +407,7 @@ mod tests {
let expected = Error::InvalidMagic;
let hs = accept_handshake(test_io, magic1, local_version, 0).wait().unwrap();
let hs = accept_handshake(test_io, 0, magic1, local_version, 0).wait().unwrap();
assert_eq!(hs.1.unwrap_err(), expected);
}
}