Merge branch 'main' into add-proof-to-batch

This commit is contained in:
Kris Nuttycombe 2022-09-15 12:41:02 -06:00 committed by GitHub
commit 4b83deb240
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 22 deletions

View File

@ -8,6 +8,11 @@ and this project adheres to Rust's notion of
## [Unreleased] ## [Unreleased]
### Added ### Added
- `orchard::Proof::add_to_batch` - `orchard::Proof::add_to_batch`
- `orchard::address::Address::diversifier`
- `orchard::keys::Diversifier::from_bytes`
- `orchard::note`:
- `RandomSeed`
- `Note::{from_parts, rseed}`
## [0.2.0] - 2022-06-24 ## [0.2.0] - 2022-06-24
### Added ### Added

View File

@ -84,3 +84,7 @@ debug = true
[profile.bench] [profile.bench]
debug = true debug = true
[patch.crates-io]
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "515b0a40ec06eb640fffa65b745166511bf56ecc" }
group = { git = "https://github.com/zkcrypto/group.git", rev = "a7f3ceb2373e9fe536996f7b4d55c797f3e667f0" }

View File

@ -30,7 +30,8 @@ impl Address {
Address { d, pk_d } Address { d, pk_d }
} }
pub(crate) fn diversifier(&self) -> Diversifier { /// Returns the [`Diversifier`] for this `Address`.
pub fn diversifier(&self) -> Diversifier {
self.d self.d
} }

View File

@ -552,7 +552,8 @@ impl DiversifierKey {
pub struct Diversifier([u8; 11]); pub struct Diversifier([u8; 11]);
impl Diversifier { impl Diversifier {
pub(crate) fn from_bytes(d: [u8; 11]) -> Self { /// Reads a diversifier from a byte array.
pub fn from_bytes(d: [u8; 11]) -> Self {
Diversifier(d) Diversifier(d)
} }
@ -1049,7 +1050,8 @@ mod tests {
NoteValue::from_raw(tv.note_v), NoteValue::from_raw(tv.note_v),
rho, rho,
RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(),
); )
.unwrap();
let cmx: ExtractedNoteCommitment = note.commitment().into(); let cmx: ExtractedNoteCommitment = note.commitment().into();
assert_eq!(cmx.to_bytes(), tv.note_cmx); assert_eq!(cmx.to_bytes(), tv.note_cmx);

View File

@ -21,7 +21,7 @@ pub use self::nullifier::Nullifier;
/// The ZIP 212 seed randomness for a note. /// The ZIP 212 seed randomness for a note.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub(crate) struct RandomSeed([u8; 32]); pub struct RandomSeed([u8; 32]);
impl RandomSeed { impl RandomSeed {
pub(crate) fn random(rng: &mut impl RngCore, rho: &Nullifier) -> Self { pub(crate) fn random(rng: &mut impl RngCore, rho: &Nullifier) -> Self {
@ -35,13 +35,17 @@ impl RandomSeed {
} }
} }
pub(crate) fn from_bytes(rseed: [u8; 32], rho: &Nullifier) -> CtOption<Self> { /// Reads a note's random seed from bytes, given the note's nullifier.
///
/// Returns `None` if the nullifier is not for the same note as the seed.
pub fn from_bytes(rseed: [u8; 32], rho: &Nullifier) -> CtOption<Self> {
let rseed = RandomSeed(rseed); let rseed = RandomSeed(rseed);
let esk = rseed.esk_inner(rho); let esk = rseed.esk_inner(rho);
CtOption::new(rseed, esk.is_some()) CtOption::new(rseed, esk.is_some())
} }
pub(crate) fn as_bytes(&self) -> &[u8; 32] { /// Returns the byte array corresponding to this seed.
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0 &self.0
} }
@ -108,18 +112,33 @@ impl PartialEq for Note {
impl Eq for Note {} impl Eq for Note {}
impl Note { impl Note {
pub(crate) fn from_parts( /// Creates a `Note` from its component parts.
///
/// Returns `None` if a valid [`NoteCommitment`] cannot be derived from the note.
///
/// # Caveats
///
/// This low-level constructor enforces that the provided arguments produce an
/// internally valid `Note`. However, it allows notes to be constructed in a way that
/// violates required security checks for note decryption, as specified in
/// [Section 4.19] of the Zcash Protocol Specification. Users of this constructor
/// should only call it with note components that have been fully validated by
/// decrypting a received note according to [Section 4.19].
///
/// [Section 4.19]: https://zips.z.cash/protocol/protocol.pdf#saplingandorchardinband
pub fn from_parts(
recipient: Address, recipient: Address,
value: NoteValue, value: NoteValue,
rho: Nullifier, rho: Nullifier,
rseed: RandomSeed, rseed: RandomSeed,
) -> Self { ) -> CtOption<Self> {
Note { let note = Note {
recipient, recipient,
value, value,
rho, rho,
rseed, rseed,
} };
CtOption::new(note, note.commitment_inner().is_some())
} }
/// Generates a new note. /// Generates a new note.
@ -134,14 +153,9 @@ impl Note {
mut rng: impl RngCore, mut rng: impl RngCore,
) -> Self { ) -> Self {
loop { loop {
let note = Note { let note = Note::from_parts(recipient, value, rho, RandomSeed::random(&mut rng, &rho));
recipient, if note.is_some().into() {
value, break note.unwrap();
rho,
rseed: RandomSeed::random(&mut rng, &rho),
};
if note.commitment_inner().is_some().into() {
break note;
} }
} }
} }
@ -180,7 +194,7 @@ impl Note {
} }
/// Returns the rseed value of this note. /// Returns the rseed value of this note.
pub(crate) fn rseed(&self) -> &RandomSeed { pub fn rseed(&self) -> &RandomSeed {
&self.rseed &self.rseed
} }

View File

@ -75,7 +75,7 @@ where
let pk_d = get_validated_pk_d(&diversifier)?; let pk_d = get_validated_pk_d(&diversifier)?;
let recipient = Address::from_parts(diversifier, pk_d); let recipient = Address::from_parts(diversifier, pk_d);
let note = Note::from_parts(recipient, value, domain.rho, rseed); let note = Option::from(Note::from_parts(recipient, value, domain.rho, rseed))?;
Some((note, recipient)) Some((note, recipient))
} }
@ -102,6 +102,7 @@ impl OrchardDomain {
impl Domain for OrchardDomain { impl Domain for OrchardDomain {
type EphemeralSecretKey = EphemeralSecretKey; type EphemeralSecretKey = EphemeralSecretKey;
type EphemeralPublicKey = EphemeralPublicKey; type EphemeralPublicKey = EphemeralPublicKey;
type PreparedEphemeralPublicKey = EphemeralPublicKey;
type SharedSecret = SharedSecret; type SharedSecret = SharedSecret;
type SymmetricKey = Hash; type SymmetricKey = Hash;
type Note = Note; type Note = Note;
@ -122,6 +123,10 @@ impl Domain for OrchardDomain {
*note.recipient().pk_d() *note.recipient().pk_d()
} }
fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey {
epk
}
fn ka_derive_public( fn ka_derive_public(
note: &Self::Note, note: &Self::Note,
esk: &Self::EphemeralSecretKey, esk: &Self::EphemeralSecretKey,
@ -138,7 +143,7 @@ impl Domain for OrchardDomain {
fn ka_agree_dec( fn ka_agree_dec(
ivk: &Self::IncomingViewingKey, ivk: &Self::IncomingViewingKey,
epk: &Self::EphemeralPublicKey, epk: &Self::PreparedEphemeralPublicKey,
) -> Self::SharedSecret { ) -> Self::SharedSecret {
epk.agree(ivk) epk.agree(ivk)
} }
@ -396,7 +401,7 @@ mod tests {
assert_eq!(ock.as_ref(), tv.ock); assert_eq!(ock.as_ref(), tv.ock);
let recipient = Address::from_parts(d, pk_d); let recipient = Address::from_parts(d, pk_d);
let note = Note::from_parts(recipient, value, rho, rseed); let note = Note::from_parts(recipient, value, rho, rseed).unwrap();
assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx);
let action = Action::from_parts( let action = Action::from_parts(