-
Notifications
You must be signed in to change notification settings - Fork 0
Orchard backward compatibility #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
d8e3472
d1aa620
086e57c
49e2f9e
83bdf70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| 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"] |
| 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> {} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This entire file should move to
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are few PRs now created around that |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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::{ | ||
|
|
@@ -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. | ||
|
|
@@ -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 | ||
|
|
@@ -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]; | ||
|
|
@@ -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( | ||
|
|
@@ -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) | ||
|
|
@@ -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) | ||
| }) | ||
| } | ||
|
|
@@ -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 { | ||
|
|
@@ -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() | ||
| } | ||
|
|
@@ -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()) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -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, | ||
|
|
@@ -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, | ||
|
|
@@ -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}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. try to reduce the diff here
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| use crate::{ | ||
| bundle::{GrothProofBytes, OutputDescription}, | ||
|
|
@@ -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], | ||
| ); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done