initial commit for Zcash support
This commit is contained in:
parent
160e8c636f
commit
a32a223395
|
@ -5,6 +5,9 @@ use crypto::dhash256;
|
||||||
use compact::Compact;
|
use compact::Compact;
|
||||||
use hash::H256;
|
use hash::H256;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Default, Clone)]
|
||||||
|
pub struct EquihashSolution(pub Vec<u8>); // TODO: len = 1344
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Serializable, Deserializable)]
|
#[derive(PartialEq, Clone, Serializable, Deserializable)]
|
||||||
pub struct BlockHeader {
|
pub struct BlockHeader {
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
|
@ -13,6 +16,7 @@ pub struct BlockHeader {
|
||||||
pub time: u32,
|
pub time: u32,
|
||||||
pub bits: Compact,
|
pub bits: Compact,
|
||||||
pub nonce: u32,
|
pub nonce: u32,
|
||||||
|
pub equihash_solution: Option<EquihashSolution>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockHeader {
|
impl BlockHeader {
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
use std::io;
|
||||||
|
use rustc_serialize::hex::ToHex;
|
||||||
|
use hash::{H256, H512};
|
||||||
|
use ser::{Error, Serializable, Deserializable, Stream, Reader};
|
||||||
|
|
||||||
|
#[derive(Clone, Serializable, Deserializable)]
|
||||||
|
pub struct ZKProof(pub Vec<u8>); // TODO: len == 296
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for ZKProof {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||||
|
write!(f, "ZKProof({})", self.0.to_hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ZKProof {
|
||||||
|
fn default() -> Self {
|
||||||
|
ZKProof([0; 296].to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for ZKProof {
|
||||||
|
fn eq(&self, c: &ZKProof) -> bool {
|
||||||
|
self.0.iter().zip(c.0.iter()).all(|(l, r)| l == r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serializable, Deserializable)]
|
||||||
|
pub struct CipherText(pub Vec<u8>); // TODO: len == 601
|
||||||
|
|
||||||
|
impl PartialEq for CipherText {
|
||||||
|
fn eq(&self, c: &CipherText) -> bool {
|
||||||
|
self.0.iter().zip(c.0.iter()).all(|(l, r)| l == r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for CipherText {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||||
|
write!(f, "CipherText({})", self.0.to_hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CipherText {
|
||||||
|
fn default() -> Self {
|
||||||
|
CipherText([0; 601].to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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: Vec<H256>,
|
||||||
|
pub commitments: Vec<H256>,
|
||||||
|
pub ephemeral_key: H256,
|
||||||
|
pub random_seed: H256,
|
||||||
|
pub macs: Vec<H256>,
|
||||||
|
pub zkproof: ZKProof,
|
||||||
|
pub ciphertexts: CipherText,
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
mod block_header;
|
mod block_header;
|
||||||
|
mod join_split;
|
||||||
mod merkle_root;
|
mod merkle_root;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ pub use primitives::{hash, bytes, bigint, compact};
|
||||||
|
|
||||||
pub use block::Block;
|
pub use block::Block;
|
||||||
pub use block_header::BlockHeader;
|
pub use block_header::BlockHeader;
|
||||||
|
pub use join_split::{JointSplit, JointSplitDescription};
|
||||||
pub use merkle_root::{merkle_root, merkle_node_hash};
|
pub use merkle_root::{merkle_root, merkle_node_hash};
|
||||||
pub use transaction::{Transaction, TransactionInput, TransactionOutput, OutPoint};
|
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 crypto::dhash256;
|
||||||
use hash::H256;
|
use hash::H256;
|
||||||
use constants::{SEQUENCE_FINAL, LOCKTIME_THRESHOLD};
|
use constants::{SEQUENCE_FINAL, LOCKTIME_THRESHOLD};
|
||||||
|
use join_split::{JointSplit, deserialize_joint_split};
|
||||||
use ser::{Error, Serializable, Deserializable, Stream, Reader};
|
use ser::{Error, Serializable, Deserializable, Stream, Reader};
|
||||||
|
|
||||||
/// Must be zero.
|
/// Must be zero.
|
||||||
|
@ -96,6 +97,7 @@ pub struct Transaction {
|
||||||
pub inputs: Vec<TransactionInput>,
|
pub inputs: Vec<TransactionInput>,
|
||||||
pub outputs: Vec<TransactionOutput>,
|
pub outputs: Vec<TransactionOutput>,
|
||||||
pub lock_time: u32,
|
pub lock_time: u32,
|
||||||
|
pub joint_split: Option<JointSplit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static str> for Transaction {
|
impl From<&'static str> for Transaction {
|
||||||
|
@ -232,7 +234,8 @@ impl Deserializable for Transaction {
|
||||||
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, Error> where Self: Sized, T: io::Read {
|
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, Error> where Self: Sized, T: io::Read {
|
||||||
let version = reader.read()?;
|
let version = reader.read()?;
|
||||||
let mut inputs: Vec<TransactionInput> = reader.read_list()?;
|
let mut inputs: Vec<TransactionInput> = reader.read_list()?;
|
||||||
let read_witness = if inputs.is_empty() {
|
|
||||||
|
let read_witness = if reader.read_transaction_witness() && inputs.is_empty() {
|
||||||
let witness_flag: u8 = reader.read()?;
|
let witness_flag: u8 = reader.read()?;
|
||||||
if witness_flag != WITNESS_FLAG {
|
if witness_flag != WITNESS_FLAG {
|
||||||
return Err(Error::MalformedData);
|
return Err(Error::MalformedData);
|
||||||
|
@ -250,11 +253,18 @@ impl Deserializable for Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let joint_split = if version >= 2 && reader.read_transaction_joint_split() {
|
||||||
|
deserialize_joint_split(reader)?
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Transaction {
|
Ok(Transaction {
|
||||||
version: version,
|
version: version,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
outputs: outputs,
|
outputs: outputs,
|
||||||
lock_time: reader.read()?,
|
lock_time: reader.read()?,
|
||||||
|
joint_split: joint_split,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ impl RawClientCore {
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
outputs: outputs,
|
outputs: outputs,
|
||||||
lock_time: lock_time,
|
lock_time: lock_time,
|
||||||
|
joint_split: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(transaction)
|
Ok(transaction)
|
||||||
|
|
|
@ -225,6 +225,7 @@ impl TransactionInputSigner {
|
||||||
outputs: outputs,
|
outputs: outputs,
|
||||||
version: self.version,
|
version: self.version,
|
||||||
lock_time: self.lock_time,
|
lock_time: self.lock_time,
|
||||||
|
joint_split: None, // TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut stream = Stream::default();
|
let mut stream = Stream::default();
|
||||||
|
|
|
@ -11,9 +11,11 @@ pub use primitives::{hash, bytes, compact};
|
||||||
|
|
||||||
pub use compact_integer::CompactInteger;
|
pub use compact_integer::CompactInteger;
|
||||||
pub use list::List;
|
pub use list::List;
|
||||||
pub use reader::{Reader, Deserializable, deserialize, deserialize_iterator, ReadIterator, Error};
|
pub use reader::{Reader, Deserializable, deserialize, deserialize_iterator, ReadIterator, Error,
|
||||||
|
DESERIALIZE_TRANSACTION_JOINT_SPLIT,
|
||||||
|
};
|
||||||
pub use stream::{
|
pub use stream::{
|
||||||
Stream, Serializable, serialize, serialize_with_flags, serialize_list, serialized_list_size,
|
Stream, Serializable, serialize, serialize_with_flags, serialize_list, serialized_list_size,
|
||||||
serialized_list_size_with_flags, SERIALIZE_TRANSACTION_WITNESS,
|
serialized_list_size_with_flags, SERIALIZE_TRANSACTION_WITNESS, SERIALIZE_TRANSACTION_JOINT_SPLIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use std::{io, marker};
|
use std::{io, marker};
|
||||||
use compact_integer::CompactInteger;
|
use compact_integer::CompactInteger;
|
||||||
|
|
||||||
|
/// Deserialize transaction witness data.
|
||||||
|
pub const DESERIALIZE_TRANSACTION_WITNESS: u32 = 0x40000000;
|
||||||
|
/// Deserialize transaction joint split data.
|
||||||
|
pub const DESERIALIZE_TRANSACTION_JOINT_SPLIT: u32 = 0x80000000;
|
||||||
|
|
||||||
pub fn deserialize<R, T>(buffer: R) -> Result<T, Error> where R: io::Read, T: Deserializable {
|
pub fn deserialize<R, T>(buffer: R) -> Result<T, Error> where R: io::Read, T: Deserializable {
|
||||||
let mut reader = Reader::from_read(buffer);
|
let mut reader = Reader::from_read(buffer);
|
||||||
let result = try!(reader.read());
|
let result = try!(reader.read());
|
||||||
|
@ -41,6 +46,7 @@ pub trait Deserializable {
|
||||||
pub struct Reader<T> {
|
pub struct Reader<T> {
|
||||||
buffer: T,
|
buffer: T,
|
||||||
peeked: Option<u8>,
|
peeked: Option<u8>,
|
||||||
|
flags: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Reader<&'a [u8]> {
|
impl<'a> Reader<&'a [u8]> {
|
||||||
|
@ -49,6 +55,7 @@ impl<'a> Reader<&'a [u8]> {
|
||||||
Reader {
|
Reader {
|
||||||
buffer: buffer,
|
buffer: buffer,
|
||||||
peeked: None,
|
peeked: None,
|
||||||
|
flags: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +84,20 @@ impl<R> Reader<R> where R: io::Read {
|
||||||
Reader {
|
Reader {
|
||||||
buffer: read,
|
buffer: read,
|
||||||
peeked: None,
|
peeked: None,
|
||||||
|
flags: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Are transactions read from this stream with witness data?
|
||||||
|
pub fn read_transaction_witness(&self) -> bool {
|
||||||
|
(self.flags & DESERIALIZE_TRANSACTION_WITNESS) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Are transactions read from this stream with the joint split data?
|
||||||
|
pub fn read_transaction_joint_split(&self) -> bool {
|
||||||
|
(self.flags & DESERIALIZE_TRANSACTION_JOINT_SPLIT) != 0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read<T>(&mut self) -> Result<T, Error> where T: Deserializable {
|
pub fn read<T>(&mut self) -> Result<T, Error> where T: Deserializable {
|
||||||
T::deserialize(self)
|
T::deserialize(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@ use std::borrow::Borrow;
|
||||||
use compact_integer::CompactInteger;
|
use compact_integer::CompactInteger;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
/// Do not serialize transaction witness data.
|
/// Serialize transaction witness data.
|
||||||
pub const SERIALIZE_TRANSACTION_WITNESS: u32 = 0x40000000;
|
pub const SERIALIZE_TRANSACTION_WITNESS: u32 = 0x40000000;
|
||||||
|
/// Serialize transaction joint split data.
|
||||||
|
pub const SERIALIZE_TRANSACTION_JOINT_SPLIT: u32 = 0x80000000;
|
||||||
|
|
||||||
pub fn serialize<T>(t: &T) -> Bytes where T: Serializable{
|
pub fn serialize<T>(t: &T) -> Bytes where T: Serializable{
|
||||||
let mut stream = Stream::default();
|
let mut stream = Stream::default();
|
||||||
|
@ -75,6 +77,11 @@ impl Stream {
|
||||||
(self.flags & SERIALIZE_TRANSACTION_WITNESS) != 0
|
(self.flags & SERIALIZE_TRANSACTION_WITNESS) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Are transactions written to this stream with the joint split data?
|
||||||
|
pub fn include_transaction_joint_split(&self) -> bool {
|
||||||
|
(self.flags & SERIALIZE_TRANSACTION_JOINT_SPLIT) != 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Serializes the struct and appends it to the end of stream.
|
/// Serializes the struct and appends it to the end of stream.
|
||||||
pub fn append<T>(&mut self, t: &T) -> &mut Self where T: Serializable {
|
pub fn append<T>(&mut self, t: &T) -> &mut Self where T: Serializable {
|
||||||
t.serialize(self);
|
t.serialize(self);
|
||||||
|
|
Loading…
Reference in New Issue