Skip to content

Variable-size note encryption support#177

Open
PaulLaux wants to merge 13 commits into
zcash:mainfrom
QED-it:zsa1
Open

Variable-size note encryption support#177
PaulLaux wants to merge 13 commits into
zcash:mainfrom
QED-it:zsa1

Conversation

@PaulLaux
Copy link
Copy Markdown

@PaulLaux PaulLaux commented Mar 26, 2026

Adapts sapling-crypto to work with the updated zcash_note_encryption crate that supports variable-size note plaintexts, a prerequisite for the OrchardZSA protocol and related changes in librustzcash.

Motivation

The upstream zcash_note_encryption crate has been refactored to make note sizes generic via const generics and associated types, replacing the previous fixed-size arrays. This PR updates sapling-crypto to conform to that new interface while keeping Sapling's own note sizes unchanged.

Key changes

  • Note size constants (COMPACT_NOTE_SIZE, NOTE_PLAINTEXT_SIZE, ENC_CIPHERTEXT_SIZE, MEMO_SIZE) are now defined locally in sapling-crypto rather than imported from zcash_note_encryption, since each protocol defines its own sizes.
  • Domain associated types NotePlaintextBytes, NoteCiphertextBytes, CompactNotePlaintextBytes, and CompactNoteCiphertextBytes are implemented using the generic NoteBytesData<N> wrapper from the encryption crate.
  • enc_ciphertext fields changed from fixed-size [u8; ENC_CIPHERTEXT_SIZE] arrays to NoteBytesData<{ ENC_CIPHERTEXT_SIZE }>.
  • ShieldedOutput trait no longer carries a const generic size parameter - implementations now provide both enc_ciphertext() and enc_ciphertext_compact() methods.
  • extract_memo replaced by split_plaintext_at_memo, which splits the plaintext into compact note bytes and memo.
  • parse_note_plaintext_without_memo_ivk/ovk now takes typed CompactNotePlaintextBytes instead of raw &[u8] / &NotePlaintextBytes.
  • Hard-coded [u8; 512] memo references replaced with [u8; MEMO_SIZE] throughout.

dmidem and others added 10 commits July 31, 2024 13:11
#2)

* Use updated backward compatible zcash_note_encryption (WIP)

* Move constants from zcash_note_encryption

* Use NoteBytes from zcash_note_encryption

* Add new line

* Use NoteBytesData

* Synchronize with updates from zcash_note_encryption for PR #2 issues resolve

* Revert toolchain Rust version back to 1.65.0

* Change zcash_note_encryption reference in Cargo.toml to point to the zsa1 branch

* Remove FIXME comments and other minor changes

* Move implementations of parse_... Domain trait methods to zcash_note_encryption crate

---------

Co-authored-by: alexeykoren <2365507+alexeykoren@users.noreply.github.com>
Co-authored-by: Dmitry Demin <dmitry@qed-it.com>
* Update ShieldedOutput/OutputDescription to return reference for enc_ciphertext

These changes were discussed and suggested in PR zcash_note_encryption#2

* Fix path zcash_note_encryption in Cargo.toml

* Move COMPACT_NOTE_SIZE, NOTE_PLAINTEXT_SIZE, and ENC_CIPHERTEXT_SIZE constant definitions from zcash_note_encryption to here

* Trigger CI

* Fix CI cargo test errors

* Use NoteBytesData<{...}> instead of <SaplingDomain as Domain>::...

* Add MEMO_SIZE constant and use it instead of the hardcoded 512 for the memo array size

* Fix code example in comment to use MEMO_SIZE

* Make MEMO_SIZE const pub to use it in the comment code example

---------

Co-authored-by: Dmitry Demin <dmitry@qed-it.com>
Update zsa1 to ustream
# Conflicts:
#	.github/workflows/ci.yml
#	src/builder.rs
#	src/pczt.rs
- Use `rev` instead of a branch in the patch section of `Cargo.toml` (to match our other repositories)
- Remove `Option` from `memo`
Comment thread src/bundle.rs Outdated
Some(&self.enc_ciphertext)
}

fn enc_ciphertext_compact(&self) -> NoteBytesData<{ COMPACT_NOTE_SIZE }> {
Copy link
Copy Markdown
Contributor

@daira daira Apr 2, 2026

Choose a reason for hiding this comment

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

Using the same type for enc ciphertexts and compact enc ciphertexts seems like a type error: they don't only differ in length, but also in semantics (compact enc ciphertexts don't have a memo and don't use authenticated encryption as of NU6.1). I don't think there are cases where we'd want to use them polymorphically.

Consider splitting/renaming NoteBytesData into two types: EncCiphertext and CompactEncCiphertext. These can even be type aliases to NoteBytesData with particular lengths if you want to make the minimal change.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Done

Comment thread src/bundle.rs Outdated
ephemeral_key: out.ephemeral_key,
cmu: out.cmu,
enc_ciphertext: out.enc_ciphertext[..COMPACT_NOTE_SIZE].try_into().unwrap(),
enc_ciphertext: out.enc_ciphertext.as_ref()[..COMPACT_NOTE_SIZE]
Copy link
Copy Markdown
Contributor

@daira daira Apr 2, 2026

Choose a reason for hiding this comment

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

This is not the enc ciphertext, so the field is misnamed. I realize it was misnamed before. Consider renaming it to enc_ciphertext_compact if that isn't too disruptive. Or that can be a separate PR. (It might need to be done for Orchard as well.)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Out of scope for this PR, as discussed.

Comment thread src/bundle.rs Outdated
}

fn enc_ciphertext_compact(&self) -> NoteBytesData<{ COMPACT_NOTE_SIZE }> {
unimplemented!("This function is not required for sapling")
Copy link
Copy Markdown
Contributor

@daira daira Apr 2, 2026

Choose a reason for hiding this comment

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

Why can't the truncation be implemented here rather than manually truncating in several other places? It seems as though those places could call enc_ciphertext_compact instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Done (implemented enc_ciphertext_compact)

Comment thread src/note_encryption.rs Outdated
type Memo = [u8; MEMO_SIZE];

type NotePlaintextBytes = NoteBytesData<{ NOTE_PLAINTEXT_SIZE }>;
type NoteCiphertextBytes = NoteBytesData<{ ENC_CIPHERTEXT_SIZE }>;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This would become type EncCiphertextBytes = EncCiphertextBytes;, etc.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Out of scope for this PR, as discussed.

Comment thread src/note_encryption.rs

fn enc_ciphertext(&self) -> &[u8; COMPACT_NOTE_SIZE] {
&self.enc_ciphertext
fn enc_ciphertext(&self) -> Option<&NoteBytesData<{ ENC_CIPHERTEXT_SIZE }>> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm. The previous API was terrible (enc_ciphertext() returning something that is not an enc ciphertext) but this also seems error-prone. Are we sure that CompactOutputDescription should impl ShieldedOutput<SaplingDomain> given that the latter has an enc_ciphertext method? Perhaps it shouldn't, and enc_ciphertext should be on a separate trait impl'd by OutputDescription.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Out of scope for this PR, as discussed.

daira
daira previously approved these changes Apr 2, 2026
Copy link
Copy Markdown
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

Abstracting over MEMO_SIZE isn't sufficient for memo bundles (the chunks are not in the enc ciphertext, an encryption key is); nor is it necessary for ZSAs (they don't change the memo size or type). So I wonder why this is necessary.

In any case, utACK to unblock further progress, even though I think this is definitely going to need to be refactored again.

@PaulLaux
Copy link
Copy Markdown
Author

PaulLaux commented Apr 15, 2026

As discussed in the meeting, we will fix the issues that require no significant changes to other crates and revisit.

Update: fixed, please see last commits and comments

ConstanceBeguier and others added 3 commits April 28, 2026 14:51
- Add type aliases for `EncCiphertext` and `CompactEncCiphertext`
- Implement `enc_ciphertext_compact` for `OutputDescription`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants