mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-31 12:31:22 +00:00
Merge branch 'master' into blake2_simd
This commit is contained in:
@@ -17,6 +17,7 @@ use sapling_crypto::jubjub::JubjubBls12;
|
||||
|
||||
pub mod block;
|
||||
pub mod keys;
|
||||
pub mod merkle_tree;
|
||||
pub mod note_encryption;
|
||||
pub mod sapling;
|
||||
mod serialize;
|
||||
|
1072
zcash_primitives/src/merkle_tree.rs
Normal file
1072
zcash_primitives/src/merkle_tree.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,109 @@
|
||||
use pairing::bls12_381::Bls12;
|
||||
//! Structs and constants specific to the Sapling shielded pool.
|
||||
|
||||
use ff::{BitIterator, PrimeField, PrimeFieldRepr};
|
||||
use pairing::bls12_381::{Bls12, Fr, FrRepr};
|
||||
use rand::OsRng;
|
||||
use sapling_crypto::{
|
||||
jubjub::{fs::Fs, FixedGenerators, JubjubBls12},
|
||||
pedersen_hash::{pedersen_hash, Personalization},
|
||||
primitives::Note,
|
||||
redjubjub::{PrivateKey, PublicKey, Signature},
|
||||
};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use crate::merkle_tree::Hashable;
|
||||
use JUBJUB;
|
||||
|
||||
pub(crate) const SAPLING_COMMITMENT_TREE_DEPTH: usize =
|
||||
sapling_crypto::circuit::sapling::TREE_DEPTH;
|
||||
|
||||
/// Compute a parent node in the Sapling commitment tree given its two children.
|
||||
pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr {
|
||||
let lhs = {
|
||||
let mut tmp = [false; 256];
|
||||
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(lhs)) {
|
||||
*a = b;
|
||||
}
|
||||
tmp
|
||||
};
|
||||
|
||||
let rhs = {
|
||||
let mut tmp = [false; 256];
|
||||
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(rhs)) {
|
||||
*a = b;
|
||||
}
|
||||
tmp
|
||||
};
|
||||
|
||||
pedersen_hash::<Bls12, _>(
|
||||
Personalization::MerkleTree(depth),
|
||||
lhs.iter()
|
||||
.map(|&x| x)
|
||||
.take(Fr::NUM_BITS as usize)
|
||||
.chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)),
|
||||
&JUBJUB,
|
||||
)
|
||||
.into_xy()
|
||||
.0
|
||||
.into_repr()
|
||||
}
|
||||
|
||||
/// A node within the Sapling commitment tree.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Node {
|
||||
repr: FrRepr,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new(repr: FrRepr) -> Self {
|
||||
Node { repr }
|
||||
}
|
||||
}
|
||||
|
||||
impl Hashable for Node {
|
||||
fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let mut repr = FrRepr::default();
|
||||
repr.read_le(&mut reader)?;
|
||||
Ok(Node::new(repr))
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
self.repr.write_le(&mut writer)
|
||||
}
|
||||
|
||||
fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self {
|
||||
Node {
|
||||
repr: merkle_hash(depth, &lhs.repr, &rhs.repr),
|
||||
}
|
||||
}
|
||||
|
||||
fn blank() -> Self {
|
||||
Node {
|
||||
repr: Note::<Bls12>::uncommitted().into_repr(),
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_root(depth: usize) -> Self {
|
||||
EMPTY_ROOTS[depth]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Node> for Fr {
|
||||
fn from(node: Node) -> Self {
|
||||
Fr::from_repr(node.repr).expect("Tree nodes should be in the prime field")
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref EMPTY_ROOTS: Vec<Node> = {
|
||||
let mut v = vec![Node::blank()];
|
||||
for d in 0..SAPLING_COMMITMENT_TREE_DEPTH {
|
||||
let next = Node::combine(d, &v[d], &v[d]);
|
||||
v.push(next);
|
||||
}
|
||||
v
|
||||
};
|
||||
}
|
||||
|
||||
/// Create the spendAuthSig for a Sapling SpendDescription.
|
||||
pub fn spend_sig(
|
||||
|
@@ -82,6 +82,37 @@ impl Vector {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Optional;
|
||||
|
||||
impl Optional {
|
||||
pub fn read<R: Read, T, F>(mut reader: R, func: F) -> io::Result<Option<T>>
|
||||
where
|
||||
F: Fn(&mut R) -> io::Result<T>,
|
||||
{
|
||||
match reader.read_u8()? {
|
||||
0 => Ok(None),
|
||||
1 => Ok(Some(func(&mut reader)?)),
|
||||
_ => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"non-canonical Option<T>",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write<W: Write, T, F>(mut writer: W, val: &Option<T>, func: F) -> io::Result<()>
|
||||
where
|
||||
F: Fn(&mut W, &T) -> io::Result<()>,
|
||||
{
|
||||
match val {
|
||||
None => writer.write_u8(0),
|
||||
Some(e) => {
|
||||
writer.write_u8(1)?;
|
||||
func(&mut writer, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -153,4 +184,47 @@ mod tests {
|
||||
eval!(vec![7; 260], expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optional() {
|
||||
macro_rules! eval {
|
||||
($value:expr, $expected:expr, $write:expr, $read:expr) => {
|
||||
let mut data = vec![];
|
||||
Optional::write(&mut data, &$value, $write).unwrap();
|
||||
assert_eq!(&data[..], &$expected[..]);
|
||||
match Optional::read(&data[..], $read) {
|
||||
Ok(v) => assert_eq!(v, $value),
|
||||
Err(e) => panic!("Unexpected error: {:?}", e),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! eval_u8 {
|
||||
($value:expr, $expected:expr) => {
|
||||
eval!($value, $expected, |w, e| w.write_u8(*e), |r| r.read_u8())
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! eval_vec {
|
||||
($value:expr, $expected:expr) => {
|
||||
eval!(
|
||||
$value,
|
||||
$expected,
|
||||
|w, v| Vector::write(w, v, |w, e| w.write_u8(*e)),
|
||||
|r| Vector::read(r, |r| r.read_u8())
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
eval_u8!(None, [0]);
|
||||
eval_u8!(Some(0), [1, 0]);
|
||||
eval_u8!(Some(1), [1, 1]);
|
||||
eval_u8!(Some(5), [1, 5]);
|
||||
|
||||
eval_vec!(None as Option<Vec<_>>, [0]);
|
||||
eval_vec!(Some(vec![]), [1, 0]);
|
||||
eval_vec!(Some(vec![0]), [1, 1, 0]);
|
||||
eval_vec!(Some(vec![1]), [1, 1, 1]);
|
||||
eval_vec!(Some(vec![5; 8]), [1, 8, 5, 5, 5, 5, 5, 5, 5, 5]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user