mirror of https://github.com/zcash/orchard.git
Ensure that Notes always have valid commitments
Implements the change from spec version 2021.1.23 to sample a new rseed if a note is generated without a valid commitment.
This commit is contained in:
parent
d8cc596bbe
commit
736de1156b
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
/// let sk = SpendingKey::from_bytes([7; 32]).unwrap();
|
/// let sk = SpendingKey::from_bytes([7; 32]).unwrap();
|
||||||
/// let address = FullViewingKey::from(&sk).default_address();
|
/// let address = FullViewingKey::from(&sk).default_address();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
d: Diversifier,
|
d: Diversifier,
|
||||||
pk_d: DiversifiedTransmissionKey,
|
pk_d: DiversifiedTransmissionKey,
|
||||||
|
|
|
@ -288,7 +288,7 @@ impl DiversifierKey {
|
||||||
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
||||||
///
|
///
|
||||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Diversifier([u8; 11]);
|
pub struct Diversifier([u8; 11]);
|
||||||
|
|
||||||
impl Diversifier {
|
impl Diversifier {
|
||||||
|
@ -408,7 +408,7 @@ impl From<&FullViewingKey> for OutgoingViewingKey {
|
||||||
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
||||||
///
|
///
|
||||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub(crate) struct DiversifiedTransmissionKey(NonIdentityPallasPoint);
|
pub(crate) struct DiversifiedTransmissionKey(NonIdentityPallasPoint);
|
||||||
|
|
||||||
impl DiversifiedTransmissionKey {
|
impl DiversifiedTransmissionKey {
|
||||||
|
|
42
src/note.rs
42
src/note.rs
|
@ -2,6 +2,7 @@
|
||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
use subtle::CtOption;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
keys::{FullViewingKey, SpendingKey},
|
keys::{FullViewingKey, SpendingKey},
|
||||||
|
@ -72,11 +73,16 @@ impl Note {
|
||||||
rho: Nullifier,
|
rho: Nullifier,
|
||||||
mut rng: impl RngCore,
|
mut rng: impl RngCore,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Note {
|
loop {
|
||||||
recipient,
|
let note = Note {
|
||||||
value,
|
recipient,
|
||||||
rho,
|
value,
|
||||||
rseed: RandomSeed::random(&mut rng),
|
rho,
|
||||||
|
rseed: RandomSeed::random(&mut rng),
|
||||||
|
};
|
||||||
|
if note.commitment_inner().is_some().into() {
|
||||||
|
break note;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +99,12 @@ impl Note {
|
||||||
let fvk: FullViewingKey = (&sk).into();
|
let fvk: FullViewingKey = (&sk).into();
|
||||||
let recipient = fvk.default_address();
|
let recipient = fvk.default_address();
|
||||||
|
|
||||||
let note = Note {
|
let note = Note::new(
|
||||||
recipient,
|
recipient,
|
||||||
value: NoteValue::zero(),
|
NoteValue::zero(),
|
||||||
rho: rho.unwrap_or_else(|| Nullifier::dummy(rng)),
|
rho.unwrap_or_else(|| Nullifier::dummy(rng)),
|
||||||
rseed: RandomSeed::random(rng),
|
rng,
|
||||||
};
|
);
|
||||||
|
|
||||||
(sk, fvk, note)
|
(sk, fvk, note)
|
||||||
}
|
}
|
||||||
|
@ -114,9 +120,22 @@ impl Note {
|
||||||
///
|
///
|
||||||
/// [notes]: https://zips.z.cash/protocol/nu5.pdf#notes
|
/// [notes]: https://zips.z.cash/protocol/nu5.pdf#notes
|
||||||
pub fn commitment(&self) -> NoteCommitment {
|
pub fn commitment(&self) -> NoteCommitment {
|
||||||
|
// `Note` will always have a note commitment by construction.
|
||||||
|
self.commitment_inner().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the commitment to this note.
|
||||||
|
///
|
||||||
|
/// This is the internal fallible API, used to check at construction time that the
|
||||||
|
/// note has a commitment. Once you have a [`Note`] object, use `note.commitment()`
|
||||||
|
/// instead.
|
||||||
|
///
|
||||||
|
/// Defined in [Zcash Protocol Spec § 3.2: Notes][notes].
|
||||||
|
///
|
||||||
|
/// [notes]: https://zips.z.cash/protocol/nu5.pdf#notes
|
||||||
|
fn commitment_inner(&self) -> CtOption<NoteCommitment> {
|
||||||
let g_d = self.recipient.g_d();
|
let g_d = self.recipient.g_d();
|
||||||
|
|
||||||
// `Note` will always have a note commitment by construction.
|
|
||||||
NoteCommitment::derive(
|
NoteCommitment::derive(
|
||||||
g_d.to_bytes(),
|
g_d.to_bytes(),
|
||||||
self.recipient.pk_d().to_bytes(),
|
self.recipient.pk_d().to_bytes(),
|
||||||
|
@ -125,7 +144,6 @@ impl Note {
|
||||||
self.rseed.psi(),
|
self.rseed.psi(),
|
||||||
(&self.rseed).into(),
|
(&self.rseed).into(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives the nullifier for this note.
|
/// Derives the nullifier for this note.
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A unique nullifier for a note.
|
/// A unique nullifier for a note.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Nullifier(pub(crate) pallas::Base);
|
pub struct Nullifier(pub(crate) pallas::Base);
|
||||||
|
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
|
const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
|
||||||
|
|
||||||
/// A Pallas point that is guaranteed to not be the identity.
|
/// A Pallas point that is guaranteed to not be the identity.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub(crate) struct NonIdentityPallasPoint(pallas::Point);
|
pub(crate) struct NonIdentityPallasPoint(pallas::Point);
|
||||||
|
|
||||||
impl Deref for NonIdentityPallasPoint {
|
impl Deref for NonIdentityPallasPoint {
|
||||||
|
|
Loading…
Reference in New Issue