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 hash::H256;
|
||||
|
||||
#[derive(Debug, PartialEq, Default, Clone)]
|
||||
pub struct EquihashSolution(pub Vec<u8>); // TODO: len = 1344
|
||||
|
||||
#[derive(PartialEq, Clone, Serializable, Deserializable)]
|
||||
pub struct BlockHeader {
|
||||
pub version: u32,
|
||||
|
@ -13,6 +16,7 @@ pub struct BlockHeader {
|
|||
pub time: u32,
|
||||
pub bits: Compact,
|
||||
pub nonce: u32,
|
||||
pub equihash_solution: Option<EquihashSolution>,
|
||||
}
|
||||
|
||||
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_header;
|
||||
mod join_split;
|
||||
mod merkle_root;
|
||||
mod transaction;
|
||||
|
||||
|
@ -28,6 +29,7 @@ pub use primitives::{hash, bytes, bigint, compact};
|
|||
|
||||
pub use block::Block;
|
||||
pub use block_header::BlockHeader;
|
||||
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};
|
||||
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 {
|
||||
|
@ -232,7 +234,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() {
|
||||
|
||||
let read_witness = if reader.read_transaction_witness() && inputs.is_empty() {
|
||||
let witness_flag: u8 = reader.read()?;
|
||||
if witness_flag != WITNESS_FLAG {
|
||||
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 {
|
||||
version: version,
|
||||
inputs: inputs,
|
||||
outputs: outputs,
|
||||
lock_time: reader.read()?,
|
||||
joint_split: joint_split,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ impl RawClientCore {
|
|||
inputs: inputs,
|
||||
outputs: outputs,
|
||||
lock_time: lock_time,
|
||||
joint_split: None,
|
||||
};
|
||||
|
||||
Ok(transaction)
|
||||
|
|
|
@ -225,6 +225,7 @@ impl TransactionInputSigner {
|
|||
outputs: outputs,
|
||||
version: self.version,
|
||||
lock_time: self.lock_time,
|
||||
joint_split: None, // TODO
|
||||
};
|
||||
|
||||
let mut stream = Stream::default();
|
||||
|
|
|
@ -11,9 +11,11 @@ pub use primitives::{hash, bytes, compact};
|
|||
|
||||
pub use compact_integer::CompactInteger;
|
||||
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::{
|
||||
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 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 {
|
||||
let mut reader = Reader::from_read(buffer);
|
||||
let result = try!(reader.read());
|
||||
|
@ -41,6 +46,7 @@ pub trait Deserializable {
|
|||
pub struct Reader<T> {
|
||||
buffer: T,
|
||||
peeked: Option<u8>,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
impl<'a> Reader<&'a [u8]> {
|
||||
|
@ -49,6 +55,7 @@ impl<'a> Reader<&'a [u8]> {
|
|||
Reader {
|
||||
buffer: buffer,
|
||||
peeked: None,
|
||||
flags: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,9 +84,20 @@ impl<R> Reader<R> where R: io::Read {
|
|||
Reader {
|
||||
buffer: read,
|
||||
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 {
|
||||
T::deserialize(self)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ use std::borrow::Borrow;
|
|||
use compact_integer::CompactInteger;
|
||||
use bytes::Bytes;
|
||||
|
||||
/// Do not serialize transaction witness data.
|
||||
/// Serialize transaction witness data.
|
||||
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{
|
||||
let mut stream = Stream::default();
|
||||
|
@ -75,6 +77,11 @@ impl Stream {
|
|||
(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.
|
||||
pub fn append<T>(&mut self, t: &T) -> &mut Self where T: Serializable {
|
||||
t.serialize(self);
|
||||
|
|
Loading…
Reference in New Issue