Skip to content
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

OrchardZSA backward compatability 0.8.0 #104

Merged
merged 113 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
8bee528
draft2
PaulLaux Jan 4, 2024
5f78e72
draft3
PaulLaux Jan 4, 2024
5221c29
draft4
PaulLaux Jan 4, 2024
e07fab9
draft5
PaulLaux Jan 4, 2024
ee0a07d
draft6
PaulLaux Jan 4, 2024
8d2d130
Generalize orchard_zsa for backward bompatibility with non-ZSA functi…
dmidem Jan 17, 2024
b177325
Minor changes in the doc comments
dmidem Jan 17, 2024
4900519
Add tests for note_encryption_v2
dmidem Jan 22, 2024
0a3d231
Rename V2 name suffixes to Vanilla, and V3 - to ZSA
dmidem Jan 24, 2024
f3ae948
Make the Circuit struct generic to support different Orchard variants…
dmidem Jan 29, 2024
fc64461
Continue Circuit generalization
dmidem Feb 6, 2024
c6f8936
Split circuit implementation into circuit_vanilla and circuit_zsa
dmidem Feb 12, 2024
ce46de0
Fix to support modified halo2
dmidem Feb 27, 2024
e5ab5d0
Add missed fields to fn print_action_circuit
dmidem Feb 27, 2024
a8dadc9
Pin half crate to 1.8.2 (to resolve MSRV conflict)
dmidem Feb 27, 2024
a8a72c2
Pin half crate to 1.8.2 for dev deps too (to resolve MSRV conflict)
dmidem Feb 27, 2024
120b090
Pin half crate to 2.2.1
dmidem Feb 27, 2024
5d5bbf1
Fix cargo clippy errors
dmidem Feb 27, 2024
97f55f9
Convert arb_... testing functions to methods of dummy generict struct…
dmidem Mar 4, 2024
90512c8
Make hash_bundle_txid_data function backwards compatible
dmidem Mar 4, 2024
416b496
Refactor note_encryption.rs:
dmidem Mar 12, 2024
a1e6cd6
Fix cargo clippy errors
dmidem Mar 12, 2024
8b28a0e
Minor fix (make action module pub)
dmidem Mar 12, 2024
fc20a5a
Make add_chip.rs a shared module between circuit_vanilla and circuit_…
dmidem Mar 15, 2024
1d68e0b
Introduce OrcharcCircuit trait to eliminate repetitive 'where crate::…
dmidem Mar 18, 2024
c820dae
Introdice NoteByteReader and NoteByteWriter traiots to use with NoteB…
dmidem Mar 19, 2024
088494a
note_encryption: extract Domain impl, OrchardDoimain and NoteBytes de…
dmidem Mar 19, 2024
46a222e
Use vec with a proper length for the concrete OrchardDomain to genera…
dmidem Mar 25, 2024
367c701
Use try_fold instead of fold when cargo clippy suggests it
dmidem Mar 25, 2024
dc97b7a
Rename domain_impl.rs in note_encryption to domain.rs
dmidem Mar 25, 2024
cc99400
Intriduce orchard_flavor module with OrchardVanilla and OrchardZSA st…
dmidem Mar 25, 2024
e2306e3
Fix naming (OrchardDomainContex to OrchardDomainBase, Curcuit to Orch…
dmidem Mar 28, 2024
d721463
Fix 'half' dep duplication in Cargo.toml
dmidem Apr 9, 2024
6ba0a38
Remove rng from AssetBase::random call
dmidem Apr 9, 2024
19dbd0a
Minor change (improive use::crate::...)
dmidem Apr 15, 2024
b6d577e
Add hashing of burn field to hash_bundle_txid_data
dmidem Apr 15, 2024
8795ca4
Revert "Add hashing of burn field to hash_bundle_txid_data"
dmidem Apr 15, 2024
58e05b1
Adapt Orchard to changes in zcash_note_encryption dependency, which n…
dmidem Apr 17, 2024
e67c792
Revert "Revert "Add hashing of burn field to hash_bundle_txid_data""
dmidem Apr 17, 2024
a9af64c
Updating test vectors to correspond to those generated by the zcash-t…
vivek-arte Apr 30, 2024
511caf6
Merge branch 'zsa1' into orchardzsa-backward-compatability-0.8.0
dmidem May 13, 2024
019cbc4
Fix zcash_note_encryption dep name (to zcash_note_encryption_zsa)
dmidem May 13, 2024
8676e26
Fix merge conflict in the bench code
dmidem May 13, 2024
c99c043
FIx compilation issues for fake_compact_action function
dmidem May 13, 2024
b883997
Change type visibility
alexeykoren Apr 17, 2024
5ea48b4
Add map_proof method
alexeykoren Apr 19, 2024
7bed5a9
Add error types for burning
alexeykoren Apr 19, 2024
fb9e09a
Address PR #100 review notes (some issues remain unresolved)
dmidem May 20, 2024
12f77f7
Fix files missed in the previous commit
dmidem May 20, 2024
f27b3ce
Remove unnecessary comment
dmidem May 20, 2024
e2abb42
Make domain public
alexeykoren May 20, 2024
da51ae2
Update/add documentation to note_encryption and circuit related modules
dmidem May 29, 2024
5dac03e
Generate a real random encrypted note in action testing
dmidem May 30, 2024
450f814
Merge branch 'orchardzsa-backward-compatability-0.8.0' into orchardzs…
alexeykoren Jun 3, 2024
efe7b38
Remove unnecessary whitespace
alexeykoren Jun 3, 2024
56c850a
Pass None instead of OutgoingViewingKey for note encryption in arb_un…
dmidem Jun 3, 2024
93645de
Shorten comments for ...Arb generics in testing
dmidem Jun 3, 2024
e10efb3
Small fixes for Orchard/ZSA backward compatability in Librustzcash (#…
dmidem Jun 3, 2024
2273de6
Remove redundant note_encryption_v3.rs
dmidem Jun 6, 2024
6353684
Add missing benches and tests for Orchard Vanilla
dmidem Jun 9, 2024
4fa556d
Partially addressed review feedback on PR #104
dmidem Jun 10, 2024
6ffb37b
Add auth mapping
alexeykoren Jun 10, 2024
8c5274d
Simplify map authorization
alexeykoren Jun 10, 2024
f7789bf
Simplify map authorization
alexeykoren Jun 10, 2024
cb0d205
Rename CircuitBase to Circuit, test_encoding_roundtrip to encoding_ro…
dmidem Jun 11, 2024
fe8b986
Restore circuit_proof_test_case.bin in src
dmidem Jun 11, 2024
9df82ad
Remove circuit_proof_test_case_zsa.bin
dmidem Jun 11, 2024
e9e65bc
Move circuit_proof_test_case.bin to circuit/circuit_proof_test_case_z…
dmidem Jun 11, 2024
576f4c4
Rename note_encryption_vanilla/note_encryption_zsa to orchard_domain_…
dmidem Jun 11, 2024
f04c205
Fix comment for rho field of OrchardDomaiBase struct
dmidem Jun 11, 2024
3cd8294
Map authorization for IssueAuth (#108)
dmidem Jun 13, 2024
9a0cdab
Rename note_encryption/acion.rs to compact_action.rs
dmidem Jun 14, 2024
4a23e66
Restructure note encryption code: move note_encryption.rs functionali…
dmidem Jun 17, 2024
8289354
Minor fix in doc comment
dmidem Jun 17, 2024
b4dec8d
Update to use backward compatible version of halo2
dmidem Jun 20, 2024
3bf500f
Add missed file for the previous commit
dmidem Jun 20, 2024
3ccee39
Restore zsa1 version of note_encryption_v3.rs and remove note_encrypt…
dmidem Jun 20, 2024
a3aac82
Move note_encryption_v3.rs to domain.rs
dmidem Jun 20, 2024
6295375
Restore changes in domain.rs
dmidem Jun 20, 2024
621a5b4
Restore zsa1 version of note_encryption_v3.rs and remove note_encrypt…
dmidem Jun 20, 2024
fdfa5dc
Move note_encryption_v3.rs to domain.rs
dmidem Jun 20, 2024
1be9604
Restore changes in domain.rs
dmidem Jun 20, 2024
1dd1a82
Rename OrchardDomain to OrchardNoteEnc, OrchardDomainBase to OrchardD…
dmidem Jun 24, 2024
cfc2ddd
Fix cargo fmt issues
dmidem Jun 24, 2024
f4ae7f2
Use PallasLookupRCConfig in circuit_vanilla/note_commit.rs
dmidem Jun 24, 2024
f677ee2
Rename halo2 types
dmidem Jul 1, 2024
e2e200d
Rename OrchardNoteEnc to OrchardDomainCommon
dmidem Jul 1, 2024
b797abc
Use OrchardFlavor instead of OrchardDomainCommon+OrchardCircuit+Orcha…
dmidem Jul 1, 2024
1363d47
Fox cargo fmt issues
dmidem Jul 1, 2024
c05d06e
Fix generic arg name compilation error in benches
dmidem Jul 1, 2024
1de980f
Fix halo2 Sinsemilla amd Merke type chip names (remove ...WithPrivate…
dmidem Jul 1, 2024
4155972
Generalize test in commit_ivk to test against both Vanilla and ZSA ci…
dmidem Jul 1, 2024
060bf95
Generalize builder::tests::shielding_bundle to run it against both Va…
dmidem Jul 2, 2024
562dcf0
Remove unnecessary FIXMEs
dmidem Jul 2, 2024
27c03b4
Refactor burn items to use NoteValue
dmidem Jul 2, 2024
aa46d52
Use associated boolean const in MyLookup trait of commit_ivk test ins…
dmidem Jul 3, 2024
1bffe59
Add test case to ensure spend adding fails when spends are disabled
dmidem Jul 3, 2024
752feb1
Address the latest PR #104 review comments
dmidem Jul 5, 2024
f45db57
Add UnauthorizedBundleWithMetadata type alias to get rid of clippy wa…
dmidem Jul 5, 2024
b7b780c
Return doc comment for ActionArb in action.rs and removed unused impo…
dmidem Jul 5, 2024
82e19da
Lock halo2 dependencies to specific commit hash
dmidem Jul 8, 2024
1e54e19
Fix issues in bundle auth data commitment and note digest generation
dmidem Jul 8, 2024
3efb12c
Return BuildError (BurnDuplicateAsset) in add_burn for duplicate asse…
dmidem Jul 8, 2024
80c7574
Modify bundle::try_map_value_balance fn to convert only value_balance…
dmidem Jul 8, 2024
b72152a
Parameterized benchmark group labels with flavor names in note_encryp…
dmidem Jul 8, 2024
0c3742a
Fix 'cargo clippy --tests' warnings
dmidem Jul 11, 2024
be1fc32
Fix panic in "compact-note-decryption/invalid" check for ZSA and Vani…
dmidem Jul 12, 2024
f0c40f2
Make OrchardDomainCommon pub
dmidem Jul 15, 2024
c4baaa7
Make from_bytes/to_bytes methods of NoteValue pub (needed for librust…
dmidem Jul 15, 2024
2d7e2a3
Minor fix of comments
dmidem Jul 15, 2024
de85554
Minor update in FIXME
dmidem Jul 15, 2024
b20ff2f
Removed extra FIXMEs
dmidem Jul 15, 2024
4aff14d
Restore parse_note_version function and remove NOTE_VERSION_BYTE asso…
dmidem Jul 16, 2024
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
2 changes: 2 additions & 0 deletions benches/note_decryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ fn bench_note_decryption<FL: OrchardFlavorBench>(c: &mut Criterion) {
let recipient = valid_ivk.address_at(0u32);
let valid_ivk = PreparedIncomingViewingKey::new(&valid_ivk);

// FIXME: should we add to the following comment that now for ZSA flavor the early
// rejection also happens when the asset is invalid?
Copy link
Collaborator

Choose a reason for hiding this comment

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

no

Copy link
Author

@dmidem dmidem Jul 15, 2024

Choose a reason for hiding this comment

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

Got it. Removed the FIXME comment.

// Compact actions don't have the full AEAD ciphertext, so ZIP 307 trial-decryption
// relies on an invalid ivk resulting in random noise for which the note commitment
// is invalid. However, in practice we still get early rejection:
Expand Down
2 changes: 1 addition & 1 deletion src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ pub(crate) mod testing {
TransmittedNoteCiphertext {
epk_bytes: encryptor.epk().to_bytes().0,
enc_ciphertext: encryptor.encrypt_note_plaintext(),
out_ciphertext: encryptor.encrypt_outgoing_plaintext(&cv_net, &cmx, rng),
out_ciphertext: encryptor.encrypt_outgoing_plaintext(cv_net, cmx, rng),
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ impl Builder {
}

/// Add an instruction to burn a given amount of a specific asset.
// FIXME: Should we add `add_burn` into `testing` (into `arb_bundle` function)
// FIXME: Should we add `add_burn` into the `into_bundle` function in this testing module
Copy link
Collaborator

Choose a reason for hiding this comment

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

no, I opened a new task for later

Copy link
Author

@dmidem dmidem Jul 15, 2024

Choose a reason for hiding this comment

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

Got it. Removed the FIXME comment.

// (like `add_spend` and `add_output` are used there)?
pub fn add_burn(&mut self, asset: AssetBase, value: NoteValue) -> Result<(), BuildError> {
use std::collections::hash_map::Entry;
Expand Down Expand Up @@ -902,8 +902,7 @@ pub struct InProgress<P, S: InProgressSignatures> {
}

impl<P, S: InProgressSignatures> InProgress<P, S> {
/// Changes this authorization from one proof type to another.
// FIXME: Change comment to "mutate the proof using the provided function"
/// Mutate the proof using the provided function.
pub fn map_proof<F, P2>(self, f: F) -> InProgress<P2, S>
where
F: FnOnce(P) -> P2,
Expand Down
7 changes: 4 additions & 3 deletions src/note_encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod orchard_domain;
mod orchard_domain_vanilla;
mod orchard_domain_zsa;

pub(crate) use orchard_domain::OrchardDomainCommon;

pub use {compact_action::CompactAction, orchard_domain::OrchardDomain};
pub use {
compact_action::CompactAction,
orchard_domain::{OrchardDomain, OrchardDomainCommon},
};
52 changes: 20 additions & 32 deletions src/note_encryption/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey,
OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret,
},
note::{AssetBase, ExtractedNoteCommitment, Note, RandomSeed, Rho},
note::{ExtractedNoteCommitment, Note, RandomSeed, Rho},
value::{NoteValue, ValueCommitment},
};

Expand Down Expand Up @@ -45,12 +45,6 @@ const ZSA_ASSET_SIZE: usize = 32;
/// The size of a ZSA compact note.
pub(super) const COMPACT_NOTE_SIZE_ZSA: usize = COMPACT_NOTE_SIZE_VANILLA + ZSA_ASSET_SIZE;

/// The version byte for Vanilla.
pub(super) const NOTE_VERSION_BYTE_V2: u8 = 0x02;

/// The version byte for ZSA.
pub(super) const NOTE_VERSION_BYTE_V3: u8 = 0x03;

pub(super) type Memo = [u8; MEMO_SIZE];

/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs].
Expand Down Expand Up @@ -78,28 +72,32 @@ pub(super) fn prf_ock_orchard(
)
}

// FIXME: consider returning enum instead of u8
/// Retrieves the version of the note plaintext.
/// Returns `Some(u8)` if the version is recognized, otherwise `None`.
pub(super) fn parse_note_version(plaintext: &[u8]) -> Option<u8> {
plaintext.first().and_then(|version| match *version {
NOTE_VERSION_BYTE_V2 | NOTE_VERSION_BYTE_V3 => Some(*version),
_ => None,
})
/// Checks if the version of the note plaintext matches the expected version for the domain.
pub(super) fn validate_note_version<D: OrchardDomainCommon>(
plaintext: &D::CompactNotePlaintextBytes,
) -> bool {
plaintext
.as_ref()
.first()
.map_or(false, |version| *version == D::NOTE_VERSION_BYTE)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to restore parse_note_version

Even if now we don't support other versions today, the encryption/decryption need to be version agnostic.

Copy link
Author

@dmidem dmidem Jul 15, 2024

Choose a reason for hiding this comment

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

@PaulLaux , I still have a question.

Inside the parse_note_plaintext_without_memo function, we need to extract the asset from the plaintext. We know three facts: the Orchard flavor (Vanilla or ZSA), the compact note size, and the note version byte. Which criteria should we use to decide how to extract the asset: either use the native asset or extract it from the plaintext? We can't rely on the note version byte only and ignore the size of the plaintext, like we did before, otherwise we get out-of-bounds panics.

On the other hand, to extract the asset, we can ignore the version byte value and use the Orchard flavor or compact note size alone to decide how we extract the asset. This is the way I implemented it now (with additional note version validation, which has nothing to do with asset extraction).

Do you mean we need to use a combination of the note version byte and the flavor/plaitext size? Like this:

let version = parse_note_version(plaintext.as_ref())?;
let asset = match version {
    NOTE_VERSION_BYTE_V2 if D::COMPACT_NOTE_SIZE == COMPACT_NOTE_SIZE_VANILLA => AssetBase::native(),
    NOTE_VERSION_BYTE_V3 if D::COMPACT_NOTE_SIZE == COMPACT_NOTE_SIZE_ZSA => {
        let bytes = plaintext.as_ref()[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA]
            .try_into()
            .unwrap();

        AssetBase::from_bytes(bytes).into()
    },
    _ => return None,
}

In this case, we don't need the new extract_asset methods of the OrchardDomainCommon I added. Or we can use extract_asset this way, for example:

let version = parse_note_version(plaintext.as_ref())?;
let asset = match version {
    NOTE_VERSION_BYTE_V2 if D::COMPACT_NOTE_SIZE == COMPACT_NOTE_SIZE_VANILLA => D::extract_asset(plaintext)?,
    NOTE_VERSION_BYTE_V3 if D::COMPACT_NOTE_SIZE == COMPACT_NOTE_SIZE_ZSA => D::extract_asset(plaintext)?,
    _ => return None,
}

Copy link
Collaborator

@PaulLaux PaulLaux Jul 15, 2024

Choose a reason for hiding this comment

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

when activating parse_note_plain_text_without_memo we already know what to expect so just:

 let asset = D::extract_asset(plaintext)?;

We already chosen the D::.

Except regular error handling / propagation inside the function, nothing else is needed.

}

/// Parses the note plaintext (excluding the memo) and extracts the note and address if valid.
/// Domain-specific requirements:
/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type.
pub(super) fn parse_note_plaintext_without_memo<Bytes: AsRef<[u8]>, F>(
pub(super) fn parse_note_plaintext_without_memo<D: OrchardDomainCommon, F>(
rho: Rho,
plaintext: &Bytes,
plaintext: &D::CompactNotePlaintextBytes,
get_validated_pk_d: F,
) -> Option<(Note, Address)>
where
F: FnOnce(&Diversifier) -> Option<DiversifiedTransmissionKey>,
{
// The unwraps below are guaranteed to succeed by the assertion above
if !validate_note_version::<D>(plaintext) {
return None;
}

// The unwraps below are guaranteed to succeed
let diversifier = Diversifier::from_bytes(
plaintext.as_ref()[NOTE_DIVERSIFIER_OFFSET..NOTE_VALUE_OFFSET]
.try_into()
Expand All @@ -121,19 +119,9 @@ where

let pk_d = get_validated_pk_d(&diversifier)?;
let recipient = Address::from_parts(diversifier, pk_d);

let asset = match parse_note_version(plaintext.as_ref())? {
NOTE_VERSION_BYTE_V2 => AssetBase::native(),
NOTE_VERSION_BYTE_V3 => {
let bytes = plaintext.as_ref()[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA]
.try_into()
.unwrap();
AssetBase::from_bytes(bytes).unwrap()
}
_ => panic!("invalid note version"),
};

let asset = D::extract_asset(plaintext)?;
let note = Option::from(Note::from_parts(recipient, value, asset, rho, rseed))?;

Some((note, recipient))
}

Expand Down Expand Up @@ -251,7 +239,7 @@ impl<D: OrchardDomainCommon> Domain for OrchardDomain<D> {
ivk: &Self::IncomingViewingKey,
plaintext: &D::CompactNotePlaintextBytes,
) -> Option<(Self::Note, Self::Recipient)> {
parse_note_plaintext_without_memo(self.rho, plaintext, |diversifier| {
parse_note_plaintext_without_memo::<D, _>(self.rho, plaintext, |diversifier| {
Some(DiversifiedTransmissionKey::derive(ivk, diversifier))
})
}
Expand All @@ -261,7 +249,7 @@ impl<D: OrchardDomainCommon> Domain for OrchardDomain<D> {
pk_d: &Self::DiversifiedTransmissionKey,
plaintext: &D::CompactNotePlaintextBytes,
) -> Option<(Self::Note, Self::Recipient)> {
parse_note_plaintext_without_memo(self.rho, plaintext, |_| Some(*pk_d))
parse_note_plaintext_without_memo::<D, _>(self.rho, plaintext, |_| Some(*pk_d))
}

fn extract_memo(
Expand Down
12 changes: 11 additions & 1 deletion src/note_encryption/orchard_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ use core::fmt;

use zcash_note_encryption_zsa::{AEAD_TAG_SIZE, MEMO_SIZE};

use crate::{action::Action, note::Rho, Note};
use crate::{
action::Action,
note::{AssetBase, Rho},
Note,
};

use super::{compact_action::CompactAction, domain::Memo};

Expand Down Expand Up @@ -62,6 +66,9 @@ pub trait OrchardDomainCommon: fmt::Debug + Clone {
/// The size of an encrypted note ciphertext, accounting for additional AEAD tag space.
const ENC_CIPHERTEXT_SIZE: usize = Self::NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE;

/// The note version byte.
const NOTE_VERSION_BYTE: u8;

Copy link
Collaborator

Choose a reason for hiding this comment

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

It is not working. we should not bake the version byte as part of the domain.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The version is a property of the note, not the encryption.

/// The raw bytes of a note plaintext.
type NotePlaintextBytes: NoteBytes;
/// The raw bytes of an encrypted note plaintext.
Expand All @@ -73,6 +80,9 @@ pub trait OrchardDomainCommon: fmt::Debug + Clone {

/// Builds NotePlaintextBytes from Note and Memo.
fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes;

/// Extracts the asset from the note plaintext.
fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option<AssetBase>;
}

/// Orchard-specific note encryption logic.
Expand Down
28 changes: 16 additions & 12 deletions src/note_encryption/orchard_domain_vanilla.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
//! This module implements the note encryption logic specific for the `OrchardVanilla` flavor.

use crate::{note::Note, orchard_flavor::OrchardVanilla};
use crate::{
note::{AssetBase, Note},
orchard_flavor::OrchardVanilla,
};

use super::{
domain::{
build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, NOTE_VERSION_BYTE_V2,
},
domain::{build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA},
orchard_domain::{NoteBytesData, OrchardDomainCommon},
};

impl OrchardDomainCommon for OrchardVanilla {
const COMPACT_NOTE_SIZE: usize = COMPACT_NOTE_SIZE_VANILLA;

const NOTE_VERSION_BYTE: u8 = 0x02;

type NotePlaintextBytes = NoteBytesData<{ Self::NOTE_PLAINTEXT_SIZE }>;
type NoteCiphertextBytes = NoteBytesData<{ Self::ENC_CIPHERTEXT_SIZE }>;
type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>;
type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>;

fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes {
let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V2, note);
let mut np = build_base_note_plaintext_bytes(Self::NOTE_VERSION_BYTE, note);

np[COMPACT_NOTE_SIZE_VANILLA..].copy_from_slice(memo);

NoteBytesData(np)
}

fn extract_asset(_plaintext: &Self::CompactNotePlaintextBytes) -> Option<AssetBase> {
Some(AssetBase::native())
}
}

#[cfg(test)]
Expand Down Expand Up @@ -55,10 +62,7 @@ mod tests {

use super::super::{
compact_action::CompactAction,
domain::{
parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard,
NOTE_VERSION_BYTE_V2,
},
domain::{parse_note_plaintext_without_memo, prf_ock_orchard, validate_note_version},
orchard_domain::{NoteBytesData, OrchardDomain},
};

Expand All @@ -81,10 +85,11 @@ mod tests {

// Decode.
let domain = OrchardDomainVanilla::for_rho(rho);
let version = parse_note_version(plaintext.as_ref()).unwrap();
let (compact, parsed_memo) = domain.extract_memo(&plaintext);

let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo(rho, &compact,
assert!(validate_note_version::<OrchardVanilla>(&compact));

let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::<OrchardVanilla, _>(rho, &compact,
|diversifier| {
assert_eq!(diversifier, &note.recipient().diversifier());
Some(*note.recipient().pk_d())
Expand All @@ -95,7 +100,6 @@ mod tests {
assert_eq!(parsed_note, note);
assert_eq!(parsed_recipient, note.recipient());
assert_eq!(&parsed_memo, memo);
assert_eq!(version, NOTE_VERSION_BYTE_V2);
}
}

Expand Down
29 changes: 19 additions & 10 deletions src/note_encryption/orchard_domain_zsa.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! This module implements the note encryption logic specific for the `OrchardZSA` flavor.

use crate::{note::Note, orchard_flavor::OrchardZSA};
use crate::{
note::{AssetBase, Note},
orchard_flavor::OrchardZSA,
};

use super::{
domain::{
build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, COMPACT_NOTE_SIZE_ZSA,
NOTE_VERSION_BYTE_V3,
},
orchard_domain::{NoteBytesData, OrchardDomainCommon},
};
Expand All @@ -18,15 +20,25 @@ impl OrchardDomainCommon for OrchardZSA {
type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>;
type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>;

const NOTE_VERSION_BYTE: u8 = 0x03;

fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes {
let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V3, note);
let mut np = build_base_note_plaintext_bytes(Self::NOTE_VERSION_BYTE, note);

np[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA]
.copy_from_slice(&note.asset().to_bytes());
np[COMPACT_NOTE_SIZE_ZSA..].copy_from_slice(memo);

NoteBytesData(np)
}

fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option<AssetBase> {
let bytes = plaintext.as_ref()[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA]
.try_into()
.unwrap();

AssetBase::from_bytes(bytes).into()
}
}

#[cfg(test)]
Expand Down Expand Up @@ -58,10 +70,7 @@ mod tests {

use super::super::{
compact_action::CompactAction,
domain::{
parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard,
NOTE_VERSION_BYTE_V3,
},
domain::{parse_note_plaintext_without_memo, prf_ock_orchard, validate_note_version},
orchard_domain::{NoteBytesData, OrchardDomain},
};

Expand All @@ -84,10 +93,11 @@ mod tests {

// Decode.
let domain = OrchardDomainZSA::for_rho(rho);
let version = parse_note_version(plaintext.as_ref()).unwrap();
let (compact, parsed_memo) = domain.extract_memo(&plaintext);

let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo(rho, &compact,
assert!(validate_note_version::<OrchardZSA>(&compact));

let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::<OrchardZSA, _>(rho, &compact,
|diversifier| {
assert_eq!(diversifier, &note.recipient().diversifier());
Some(*note.recipient().pk_d())
Expand All @@ -98,7 +108,6 @@ mod tests {
assert_eq!(parsed_note, note);
assert_eq!(parsed_recipient, note.recipient());
assert_eq!(&parsed_memo, memo);
assert_eq!(version, NOTE_VERSION_BYTE_V3);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ impl NoteValue {
NoteValue(value)
}

pub(crate) fn from_bytes(bytes: [u8; 8]) -> Self {
/// Creates a note value from a byte array.
pub fn from_bytes(bytes: [u8; 8]) -> Self {
NoteValue(u64::from_le_bytes(bytes))
}

pub(crate) fn to_bytes(self) -> [u8; 8] {
/// Converts the note value to a byte array.
pub fn to_bytes(self) -> [u8; 8] {
self.0.to_le_bytes()
}

Expand Down
Loading