Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
494 changes: 211 additions & 283 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ harness = false
[[bench]]
name = "pedersen_hash"
harness = false

[patch.crates-io]
zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "1.65.0"
channel = "1.70.0"
components = ["clippy", "rustfmt"]
2 changes: 1 addition & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl PreparedOutputInfo {
cv,
cmu,
epk.to_bytes(),
enc_ciphertext,
enc_ciphertext.0,
out_ciphertext,
zkproof,
)
Expand Down
14 changes: 10 additions & 4 deletions src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use memuse::DynamicUsage;
use redjubjub::{Binding, SpendAuth};

use zcash_note_encryption::{
EphemeralKeyBytes, ShieldedOutput, COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE, OUT_CIPHERTEXT_SIZE,
EphemeralKeyBytes, ShieldedOutput, OUT_CIPHERTEXT_SIZE,
};

use crate::{
Expand All @@ -15,6 +15,8 @@ use crate::{
value::ValueCommitment,
Nullifier,
};
use crate::note_bytes::NoteBytes;
use crate::note_encryption::{COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE};

pub type GrothProofBytes = [u8; GROTH_PROOF_SIZE];

Expand Down Expand Up @@ -404,7 +406,7 @@ impl<Proof: DynamicUsage> DynamicUsage for OutputDescription<Proof> {
}
}

impl<A> ShieldedOutput<SaplingDomain, ENC_CIPHERTEXT_SIZE> for OutputDescription<A> {
impl<A> ShieldedOutput<SaplingDomain> for OutputDescription<A> {
fn ephemeral_key(&self) -> EphemeralKeyBytes {
self.ephemeral_key.clone()
}
Expand All @@ -413,8 +415,12 @@ impl<A> ShieldedOutput<SaplingDomain, ENC_CIPHERTEXT_SIZE> for OutputDescription
self.cmu.to_bytes()
}

fn enc_ciphertext(&self) -> &[u8; ENC_CIPHERTEXT_SIZE] {
&self.enc_ciphertext
fn enc_ciphertext(&self) -> Option<NoteBytes<ENC_CIPHERTEXT_SIZE>> {
Some(NoteBytes(self.enc_ciphertext))
}

fn enc_ciphertext_compact(&self) -> <SaplingDomain as zcash_note_encryption::Domain>::CompactNoteCiphertextBytes {
todo!()
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub mod util;
pub mod value;
mod verifier;
pub mod zip32;
mod note_bytes;

pub use address::PaymentAddress;
pub use bundle::Bundle;
Expand Down
43 changes: 43 additions & 0 deletions src/note_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// Represents a fixed-size array of bytes for note components.
#[derive(Clone, Copy, Debug)]
pub struct NoteBytes<const N: usize>(pub [u8; N]);

impl<const N: usize> AsRef<[u8]> for NoteBytes<N> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}

impl<const N: usize> AsMut<[u8]> for NoteBytes<N> {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}

// FIXME: consider implementing and using TryFrom instead
impl<const N: usize> From<&[u8]> for NoteBytes<N> {
fn from(s: &[u8]) -> Self {
Self(s.try_into().unwrap())
}
}

impl<const N: usize> From<(&[u8], &[u8])> for NoteBytes<N> {
fn from(s: (&[u8], &[u8])) -> Self {
Self([s.0, s.1].concat().try_into().unwrap())
}
}

/// Defines the ability to concatenate two byte slices.
pub trait NoteByteConcat: for<'a> From<(&'a [u8], &'a [u8])> {}

impl<const N: usize> NoteByteConcat for NoteBytes<N> {}

/// Defines the behavior for types that can provide read-only access to their internal byte array.
pub trait NoteByteReader: AsRef<[u8]> + for<'a> From<&'a [u8]> + Clone + Copy {}

impl<const N: usize> NoteByteReader for NoteBytes<N> {}

/// Defines the behavior for types that support both read and write access to their internal byte array.
pub trait NoteByteWriter: NoteByteReader + AsMut<[u8]> {}

impl<const N: usize> NoteByteWriter for NoteBytes<N> {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire file should move to zcash_note_encryption and reused here and in Orchard.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are few PRs now created around that

70 changes: 44 additions & 26 deletions src/note_encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use rand_core::RngCore;
use zcash_note_encryption::{
try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ock,
try_output_recovery_with_ovk, BatchDomain, Domain, EphemeralKeyBytes, NoteEncryption,
NotePlaintextBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, COMPACT_NOTE_SIZE,
ENC_CIPHERTEXT_SIZE, NOTE_PLAINTEXT_SIZE, OUT_PLAINTEXT_SIZE,
OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput,
AEAD_TAG_SIZE, OUT_PLAINTEXT_SIZE,
};

use crate::{
Expand All @@ -28,10 +28,21 @@ use crate::{
use super::note::ExtractedNoteCommitment;

pub use crate::keys::{PreparedEphemeralPublicKey, PreparedIncomingViewingKey};
use crate::note_bytes::NoteBytes;

pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingKDF";
pub const PRF_OCK_PERSONALIZATION: &[u8; 16] = b"Zcash_Derive_ock";

/// The size of a compact note.
pub const COMPACT_NOTE_SIZE: usize = 1 + // version
11 + // diversifier
8 + // value
32; // rseed (or rcm prior to ZIP 212)
/// The size of NotePlaintextBytes.
pub const NOTE_PLAINTEXT_SIZE: usize = COMPACT_NOTE_SIZE + 512;
/// The size of an encrypted note plaintext.
pub const ENC_CIPHERTEXT_SIZE: usize = NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE;

/// Sapling PRF^ock.
///
/// Implemented per section 5.4.2 of the Zcash Protocol Specification.
Expand Down Expand Up @@ -70,12 +81,13 @@ pub enum Zip212Enforcement {
/// valid Sapling diversifier.
fn sapling_parse_note_plaintext_without_memo<F>(
domain: &SaplingDomain,
plaintext: &[u8],
plaintext: &<SaplingDomain as Domain>::CompactNotePlaintextBytes,
get_pk_d: F,
) -> Option<(Note, PaymentAddress)>
where
F: FnOnce(&Diversifier) -> Option<DiversifiedTransmissionKey>,
{
let plaintext = plaintext.as_ref();
assert!(plaintext.len() >= COMPACT_NOTE_SIZE);

// Check note plaintext version
Expand Down Expand Up @@ -184,7 +196,7 @@ impl Domain for SaplingDomain {
dhsecret.kdf_sapling(epk)
}

fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> NotePlaintextBytes {
fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> Self::NotePlaintextBytes {
// Note plaintext encoding is defined in section 5.5 of the Zcash Protocol
// Specification.
let mut input = [0; NOTE_PLAINTEXT_SIZE];
Expand All @@ -208,7 +220,7 @@ impl Domain for SaplingDomain {

input[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE].copy_from_slice(&memo[..]);

NotePlaintextBytes(input)
Self::NotePlaintextBytes::from(input.as_ref())
}

fn derive_ock(
Expand Down Expand Up @@ -245,7 +257,7 @@ impl Domain for SaplingDomain {
fn parse_note_plaintext_without_memo_ivk(
&self,
ivk: &Self::IncomingViewingKey,
plaintext: &[u8],
plaintext: &Self::CompactNotePlaintextBytes,
) -> Option<(Self::Note, Self::Recipient)> {
sapling_parse_note_plaintext_without_memo(self, plaintext, |diversifier| {
DiversifiedTransmissionKey::derive(ivk, diversifier)
Expand All @@ -255,9 +267,9 @@ impl Domain for SaplingDomain {
fn parse_note_plaintext_without_memo_ovk(
&self,
pk_d: &Self::DiversifiedTransmissionKey,
plaintext: &NotePlaintextBytes,
plaintext: &Self::CompactNotePlaintextBytes,
) -> Option<(Self::Note, Self::Recipient)> {
sapling_parse_note_plaintext_without_memo(self, &plaintext.0, |diversifier| {
sapling_parse_note_plaintext_without_memo(self, plaintext, |diversifier| {
diversifier.g_d().map(|_| *pk_d)
})
}
Expand All @@ -282,11 +294,18 @@ impl Domain for SaplingDomain {
.into()
}

fn extract_memo(&self, plaintext: &NotePlaintextBytes) -> Self::Memo {
plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]
.try_into()
.expect("correct length")
fn extract_memo(&self, plaintext: &Self::NotePlaintextBytes) -> (Self::CompactNotePlaintextBytes, Self::Memo) {
let (compact, memo) = plaintext.0.split_at(COMPACT_NOTE_SIZE);
(
Self::CompactNotePlaintextBytes::from(compact),
memo.try_into().unwrap(),
)
}

type NotePlaintextBytes = NoteBytes<{ NOTE_PLAINTEXT_SIZE }>;
type NoteCiphertextBytes = NoteBytes<{ ENC_CIPHERTEXT_SIZE }>;
type CompactNotePlaintextBytes = NoteBytes<{ COMPACT_NOTE_SIZE }>;
type CompactNoteCiphertextBytes = NoteBytes<{ COMPACT_NOTE_SIZE }>;
}

impl BatchDomain for SaplingDomain {
Expand Down Expand Up @@ -331,7 +350,7 @@ pub struct CompactOutputDescription {

memuse::impl_no_dynamic_usage!(CompactOutputDescription);

impl ShieldedOutput<SaplingDomain, COMPACT_NOTE_SIZE> for CompactOutputDescription {
impl ShieldedOutput<SaplingDomain> for CompactOutputDescription {
fn ephemeral_key(&self) -> EphemeralKeyBytes {
self.ephemeral_key.clone()
}
Expand All @@ -340,8 +359,12 @@ impl ShieldedOutput<SaplingDomain, COMPACT_NOTE_SIZE> for CompactOutputDescripti
self.cmu.to_bytes()
}

fn enc_ciphertext(&self) -> &[u8; COMPACT_NOTE_SIZE] {
&self.enc_ciphertext
fn enc_ciphertext(&self) -> Option<<SaplingDomain as Domain>::NoteCiphertextBytes> {
None
}

fn enc_ciphertext_compact(&self) -> <SaplingDomain as Domain>::CompactNoteCiphertextBytes {
NoteBytes::from(self.enc_ciphertext.as_ref())
}
}

Expand Down Expand Up @@ -406,7 +429,7 @@ pub fn plaintext_version_is_valid(zip212_enforcement: Zip212Enforcement, leadbyt
}
}

pub fn try_sapling_note_decryption<Output: ShieldedOutput<SaplingDomain, ENC_CIPHERTEXT_SIZE>>(
pub fn try_sapling_note_decryption<Output: ShieldedOutput<SaplingDomain>>(
ivk: &PreparedIncomingViewingKey,
output: &Output,
zip212_enforcement: Zip212Enforcement,
Expand All @@ -416,7 +439,7 @@ pub fn try_sapling_note_decryption<Output: ShieldedOutput<SaplingDomain, ENC_CIP
}

pub fn try_sapling_compact_note_decryption<
Output: ShieldedOutput<SaplingDomain, COMPACT_NOTE_SIZE>,
Output: ShieldedOutput<SaplingDomain>,
>(
ivk: &PreparedIncomingViewingKey,
output: &Output,
Expand Down Expand Up @@ -473,16 +496,11 @@ mod tests {
use rand_core::{CryptoRng, RngCore};

use zcash_note_encryption::{
batch, EphemeralKeyBytes, NoteEncryption, OutgoingCipherKey, ENC_CIPHERTEXT_SIZE,
NOTE_PLAINTEXT_SIZE, OUT_CIPHERTEXT_SIZE, OUT_PLAINTEXT_SIZE,
batch, EphemeralKeyBytes, NoteEncryption, OutgoingCipherKey,
OUT_CIPHERTEXT_SIZE, OUT_PLAINTEXT_SIZE,
};

use super::{
prf_ock, sapling_note_encryption, try_sapling_compact_note_decryption,
try_sapling_note_decryption, try_sapling_output_recovery,
try_sapling_output_recovery_with_ock, CompactOutputDescription, SaplingDomain,
Zip212Enforcement,
};
use super::{prf_ock, sapling_note_encryption, try_sapling_compact_note_decryption, try_sapling_note_decryption, try_sapling_output_recovery, try_sapling_output_recovery_with_ock, CompactOutputDescription, SaplingDomain, Zip212Enforcement, NOTE_PLAINTEXT_SIZE, ENC_CIPHERTEXT_SIZE};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to reduce the diff here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


use crate::{
bundle::{GrothProofBytes, OutputDescription},
Expand Down Expand Up @@ -560,7 +578,7 @@ mod tests {
cv,
cmu,
epk.to_bytes(),
ne.encrypt_note_plaintext(),
ne.encrypt_note_plaintext().0,
out_ciphertext,
[0u8; GROTH_PROOF_SIZE],
);
Expand Down