Merge branch 'master' into blake2_simd

This commit is contained in:
str4d
2019-07-18 18:22:20 +02:00
committed by GitHub
10 changed files with 1271 additions and 104 deletions

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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(

View File

@@ -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]);
}
}