-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
55 changed files
with
13,522 additions
and
11,072 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)), | ||
) | ||
}) | ||
} | ||
} |
Oops, something went wrong.