Skip to content

Commit

Permalink
Bring in refactor of the crate
Browse files Browse the repository at this point in the history
This refactor was performed over several years. The crate was previously
focused on the Sapling circuit; it now encompasses the Sapling protocol,
and has types better suited to use in non-circuit contexts. Many of the
circuit helper types were moved into the `bellman` crate, and the Sprout
circuit was left in `zcash_primitives`.

Source: https://github.com/zcash/librustzcash
Rev: zcash/librustzcash@6acc64e
  • Loading branch information
str4d committed Dec 11, 2023
1 parent 49017b4 commit df6681c
Show file tree
Hide file tree
Showing 55 changed files with 13,522 additions and 11,072 deletions.
81 changes: 61 additions & 20 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,31 +1,72 @@
[package]
authors = ["Sean Bowe <[email protected]>"]
description = "Cryptographic library for Zcash Sapling"
documentation = "https://github.com/zcash-hackworks/sapling"
homepage = "https://github.com/zcash-hackworks/sapling"
license = "MIT/Apache-2.0"
name = "sapling-crypto"
repository = "https://github.com/zcash-hackworks/sapling"
version = "0.0.1"

[dependencies.pairing]
version = "0.14.2"
features = ["expose-arith"]
authors = [
"Sean Bowe <[email protected]>",
"Jack Grigg <[email protected]>",
"Kris Nuttycombe <[email protected]>",
]
edition = "2021"
rust-version = "1.65"
description = "Cryptographic library for Zcash Sapling"
homepage = "https://github.com/zcash/sapling-crypto"
repository = "https://github.com/zcash/sapling-crypto"
license = "MIT OR Apache-2.0"

[dependencies]
rand = "0.4"
digest = "0.7"
bellman = "0.1"
ff = "0.13"
group = "0.13"

bls12_381 = "0.8"
jubjub = "0.10"
redjubjub = "0.7"
zcash_spec = "0.1"

# Circuits
bellman = { version = "0.14", default-features = false, features = ["groth16"] }

# CSPRNG
rand = "0.8"
rand_core = "0.6"

# Digests
blake2b_simd = "1"
blake2s_simd = "1"

# Encodings
byteorder = "1"
hex = "0.4"

# Logging and metrics
memuse = "0.2.1"
tracing = "0.1"

# Note Commitment Trees
bitvec = "1"
incrementalmerkletree = "0.5"

# Note encryption
zcash_note_encryption = "0.4"

# Secret management
subtle = "2.2.3"

# Static constants
lazy_static = "1"

# Test dependencies
proptest = { version = "1", optional = true }

[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
# ZIP 32
aes = "0.8"
fpe = "0.6"
zip32 = "0.1"

[dev-dependencies]
hex-literal = "0.1"
rust-crypto = "0.2"
chacha20poly1305 = "0.10"
proptest = "1"
rand_xorshift = "0.3"

[features]
default = ["u128-support"]
u128-support = ["pairing/u128-support"]
multicore = ["bellman/multicore"]
test-dependencies = ["proptest"]
118 changes: 118 additions & 0 deletions src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use super::{
keys::{DiversifiedTransmissionKey, Diversifier},
note::{Note, Rseed},
value::NoteValue,
};

/// A Sapling payment address.
///
/// # Invariants
///
/// - `diversifier` is guaranteed to be valid for Sapling (only 50% of diversifiers are).
/// - `pk_d` is guaranteed to be prime-order (i.e. in the prime-order subgroup of Jubjub,
/// and not the identity).
#[derive(Clone, Copy, Debug)]
pub struct PaymentAddress {
pk_d: DiversifiedTransmissionKey,
diversifier: Diversifier,
}

impl PartialEq for PaymentAddress {
fn eq(&self, other: &Self) -> bool {
self.pk_d == other.pk_d && self.diversifier == other.diversifier
}
}

impl Eq for PaymentAddress {}

impl PaymentAddress {
/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
///
/// Returns None if `diversifier` is not valid for Sapling, or `pk_d` is the identity.
/// Note that we cannot verify in this constructor that `pk_d` is derived from
/// `diversifier`, so addresses for which these values have no known relationship
/// (and therefore no-one can receive funds at them) can still be constructed.
pub fn from_parts(diversifier: Diversifier, pk_d: DiversifiedTransmissionKey) -> Option<Self> {
// Check that the diversifier is valid
diversifier.g_d()?;

Self::from_parts_unchecked(diversifier, pk_d)
}

/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
///
/// Returns None if `pk_d` is the identity. The caller must check that `diversifier`
/// is valid for Sapling.
pub(crate) fn from_parts_unchecked(
diversifier: Diversifier,
pk_d: DiversifiedTransmissionKey,
) -> Option<Self> {
if pk_d.is_identity() {
None
} else {
Some(PaymentAddress { pk_d, diversifier })
}
}

/// Parses a PaymentAddress from bytes.
pub fn from_bytes(bytes: &[u8; 43]) -> Option<Self> {
let diversifier = {
let mut tmp = [0; 11];
tmp.copy_from_slice(&bytes[0..11]);
Diversifier(tmp)
};

let pk_d = DiversifiedTransmissionKey::from_bytes(bytes[11..43].try_into().unwrap());
if pk_d.is_some().into() {
// The remaining invariants are checked here.
PaymentAddress::from_parts(diversifier, pk_d.unwrap())
} else {
None
}
}

/// Returns the byte encoding of this `PaymentAddress`.
pub fn to_bytes(&self) -> [u8; 43] {
let mut bytes = [0; 43];
bytes[0..11].copy_from_slice(&self.diversifier.0);
bytes[11..].copy_from_slice(&self.pk_d.to_bytes());
bytes
}

/// Returns the [`Diversifier`] for this `PaymentAddress`.
pub fn diversifier(&self) -> &Diversifier {
&self.diversifier
}

/// Returns `pk_d` for this `PaymentAddress`.
pub fn pk_d(&self) -> &DiversifiedTransmissionKey {
&self.pk_d
}

pub(crate) fn g_d(&self) -> jubjub::SubgroupPoint {
self.diversifier.g_d().expect("checked at construction")
}

pub fn create_note(&self, value: NoteValue, rseed: Rseed) -> Note {
Note::from_parts(*self, value, rseed)
}
}

#[cfg(any(test, feature = "test-dependencies"))]
pub(super) mod testing {
use proptest::prelude::*;

use super::{
super::keys::{testing::arb_incoming_viewing_key, Diversifier, SaplingIvk},
PaymentAddress,
};

pub fn arb_payment_address() -> impl Strategy<Value = PaymentAddress> {
arb_incoming_viewing_key().prop_flat_map(|ivk: SaplingIvk| {
any::<[u8; 11]>().prop_filter_map(
"Sampled diversifier must generate a valid Sapling payment address.",
move |d| ivk.to_payment_address(Diversifier(d)),
)
})
}
}
Loading

0 comments on commit df6681c

Please sign in to comment.