2019-04-16 00:29:09 -07:00
|
|
|
//! Structs and constants specific to the Sapling shielded pool.
|
|
|
|
|
2021-03-04 09:26:00 -08:00
|
|
|
pub mod group_hash;
|
2021-03-04 09:48:04 -08:00
|
|
|
pub mod prover;
|
2021-03-04 09:33:14 -08:00
|
|
|
pub mod redjubjub;
|
2021-03-04 09:26:00 -08:00
|
|
|
|
2019-08-06 02:46:40 -07:00
|
|
|
use crate::{
|
2020-07-01 13:26:54 -07:00
|
|
|
constants::SPENDING_KEY_GENERATOR,
|
2018-10-03 05:18:39 -07:00
|
|
|
pedersen_hash::{pedersen_hash, Personalization},
|
2019-04-15 16:27:44 -07:00
|
|
|
primitives::Note,
|
2018-08-14 15:43:33 -07:00
|
|
|
};
|
2020-09-08 16:07:51 -07:00
|
|
|
use bitvec::{order::Lsb0, view::AsBits};
|
|
|
|
use ff::PrimeField;
|
2020-07-01 13:26:54 -07:00
|
|
|
use group::{Curve, GroupEncoding};
|
2019-10-08 06:06:02 -07:00
|
|
|
use lazy_static::lazy_static;
|
2019-08-15 09:39:55 -07:00
|
|
|
use rand_core::{CryptoRng, RngCore};
|
2019-04-15 16:27:44 -07:00
|
|
|
use std::io::{self, Read, Write};
|
2018-08-14 15:43:33 -07:00
|
|
|
|
2021-03-04 09:33:14 -08:00
|
|
|
use self::redjubjub::{PrivateKey, PublicKey, Signature};
|
2019-04-15 16:27:44 -07:00
|
|
|
use crate::merkle_tree::Hashable;
|
2018-10-03 05:18:39 -07:00
|
|
|
|
2019-08-05 14:45:12 -07:00
|
|
|
pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32;
|
2019-04-15 16:27:44 -07:00
|
|
|
|
2018-10-03 05:18:39 -07:00
|
|
|
/// Compute a parent node in the Sapling commitment tree given its two children.
|
2020-07-01 13:26:54 -07:00
|
|
|
pub fn merkle_hash(depth: usize, lhs: &[u8; 32], rhs: &[u8; 32]) -> [u8; 32] {
|
2018-10-03 05:18:39 -07:00
|
|
|
let lhs = {
|
|
|
|
let mut tmp = [false; 256];
|
2020-09-08 16:07:51 -07:00
|
|
|
for (a, b) in tmp.iter_mut().zip(lhs.as_bits::<Lsb0>()) {
|
|
|
|
*a = *b;
|
2018-10-03 05:18:39 -07:00
|
|
|
}
|
|
|
|
tmp
|
|
|
|
};
|
|
|
|
|
|
|
|
let rhs = {
|
|
|
|
let mut tmp = [false; 256];
|
2020-09-08 16:07:51 -07:00
|
|
|
for (a, b) in tmp.iter_mut().zip(rhs.as_bits::<Lsb0>()) {
|
|
|
|
*a = *b;
|
2018-10-03 05:18:39 -07:00
|
|
|
}
|
|
|
|
tmp
|
|
|
|
};
|
|
|
|
|
2020-07-01 13:26:54 -07:00
|
|
|
jubjub::ExtendedPoint::from(pedersen_hash(
|
2018-10-03 05:18:39 -07:00
|
|
|
Personalization::MerkleTree(depth),
|
|
|
|
lhs.iter()
|
2019-08-02 03:25:00 -07:00
|
|
|
.copied()
|
2020-07-01 13:26:54 -07:00
|
|
|
.take(bls12_381::Scalar::NUM_BITS as usize)
|
|
|
|
.chain(
|
|
|
|
rhs.iter()
|
|
|
|
.copied()
|
|
|
|
.take(bls12_381::Scalar::NUM_BITS as usize),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
.to_affine()
|
|
|
|
.get_u()
|
2020-05-01 23:55:13 -07:00
|
|
|
.to_repr()
|
2018-10-03 05:18:39 -07:00
|
|
|
}
|
|
|
|
|
2019-04-16 00:29:09 -07:00
|
|
|
/// A node within the Sapling commitment tree.
|
2019-04-15 16:27:44 -07:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
pub struct Node {
|
2020-07-01 13:26:54 -07:00
|
|
|
repr: [u8; 32],
|
2019-04-15 16:27:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Node {
|
2020-07-01 13:26:54 -07:00
|
|
|
pub fn new(repr: [u8; 32]) -> Self {
|
2019-04-15 16:27:44 -07:00
|
|
|
Node { repr }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Hashable for Node {
|
|
|
|
fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
2020-08-21 10:22:29 -07:00
|
|
|
let mut repr = [0u8; 32];
|
2020-07-01 13:26:54 -07:00
|
|
|
reader.read_exact(&mut repr)?;
|
2019-04-15 16:27:44 -07:00
|
|
|
Ok(Node::new(repr))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
2020-04-22 22:32:04 -07:00
|
|
|
writer.write_all(self.repr.as_ref())
|
2019-04-15 16:27:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self {
|
|
|
|
Node {
|
|
|
|
repr: merkle_hash(depth, &lhs.repr, &rhs.repr),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn blank() -> Self {
|
|
|
|
Node {
|
2020-07-01 13:26:54 -07:00
|
|
|
repr: Note::uncommitted().to_repr(),
|
2019-04-15 16:27:44 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn empty_root(depth: usize) -> Self {
|
|
|
|
EMPTY_ROOTS[depth]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:26:54 -07:00
|
|
|
impl From<Node> for bls12_381::Scalar {
|
2019-04-15 16:27:44 -07:00
|
|
|
fn from(node: Node) -> Self {
|
2020-07-01 13:26:54 -07:00
|
|
|
bls12_381::Scalar::from_repr(node.repr).expect("Tree nodes should be in the prime field")
|
2019-04-15 16:27:44 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-08-14 15:43:33 -07:00
|
|
|
/// Create the spendAuthSig for a Sapling SpendDescription.
|
2019-06-12 15:12:55 -07:00
|
|
|
pub fn spend_sig<R: RngCore + CryptoRng>(
|
2020-07-01 13:26:54 -07:00
|
|
|
ask: PrivateKey,
|
|
|
|
ar: jubjub::Fr,
|
2018-08-14 15:43:33 -07:00
|
|
|
sighash: &[u8; 32],
|
2019-06-12 15:12:55 -07:00
|
|
|
rng: &mut R,
|
2020-10-21 11:37:21 -07:00
|
|
|
) -> Signature {
|
|
|
|
spend_sig_internal(ask, ar, sighash, rng)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn spend_sig_internal<R: RngCore>(
|
|
|
|
ask: PrivateKey,
|
|
|
|
ar: jubjub::Fr,
|
|
|
|
sighash: &[u8; 32],
|
|
|
|
rng: &mut R,
|
2018-08-14 15:43:33 -07:00
|
|
|
) -> Signature {
|
|
|
|
// We compute `rsk`...
|
|
|
|
let rsk = ask.randomize(ar);
|
|
|
|
|
|
|
|
// We compute `rk` from there (needed for key prefixing)
|
2020-07-01 13:26:54 -07:00
|
|
|
let rk = PublicKey::from_private(&rsk, SPENDING_KEY_GENERATOR);
|
2018-08-14 15:43:33 -07:00
|
|
|
|
|
|
|
// Compute the signature's message for rk/spend_auth_sig
|
|
|
|
let mut data_to_be_signed = [0u8; 64];
|
2020-07-01 13:26:54 -07:00
|
|
|
data_to_be_signed[0..32].copy_from_slice(&rk.0.to_bytes());
|
2018-08-14 15:43:33 -07:00
|
|
|
(&mut data_to_be_signed[32..64]).copy_from_slice(&sighash[..]);
|
|
|
|
|
|
|
|
// Do the signing
|
2020-07-01 13:26:54 -07:00
|
|
|
rsk.sign(&data_to_be_signed, rng, SPENDING_KEY_GENERATOR)
|
2018-08-14 15:43:33 -07:00
|
|
|
}
|