Skip to content

OrchardZSA reference implementation#372

Closed
PaulLaux wants to merge 141 commits intozcash:mainfrom
QED-it:zsa1
Closed

OrchardZSA reference implementation#372
PaulLaux wants to merge 141 commits intozcash:mainfrom
QED-it:zsa1

Conversation

@PaulLaux
Copy link

@PaulLaux PaulLaux commented Jan 31, 2023

This PR implements draft ZIP 226 (Transfer and Burn of Zcash Shielded Assets) and draft ZIP 227 (Issuance of Zcash Shielded Assets).

  • Burning mechanism: the ability to publicly burn ZSA notes. This is done by adding a burn field inside the Orchard bundle and the ability to utilize it. In addition the changes to bvk and bsk to support this change. See ZSA burn functionality QED-it/orchard#35 for a full list of changes.
/// A bundle of actions to be applied to the ledger.
pub struct Bundle<A: Authorization, V, P: OrchardPrimitives> {
    /// The list of actions that make up this bundle.
    actions: NonEmpty<Action<A::SpendAuth, P>>,
    /// Orchard-specific transaction-level flags for this bundle.
    flags: Flags,
    /// The net value moved out of the Orchard shielded pool.
    ///
    /// This is the sum of Orchard spends minus the sum of Orchard outputs.
    value_balance: V,
    /// Assets intended for burning
    burn: Vec<(AssetBase, NoteValue)>,
    /// The root of the Orchard commitment tree that this bundle commits to.
    anchor: Anchor,
    /// Block height after which this Bundle's Actions are invalid by consensus.
    ///
    /// For the OrchardZSA protocol, `expiry_height` is set to 0, indicating no expiry.
    /// This field is reserved for future use.
    expiry_height: u32,
    /// The authorization for this bundle.
    authorization: A,
}
}
  • Note Encryption: We extended the Domain trait in the zcash_note_encryption crate to support various lengths for COMPACT_NOTE_SIZE by converting the relevant constants into trait-specific types. Later, implemented OrchardDomainV3 to support the new note structure.
  • Updated the Python implementation to support the changes. See ZSA test vectors modifications zcash-test-vectors#108 for details.

Also included:

  • Test vectors for AssetID derivatio
  • Split note mechanism.
  • Circuit changes to support AssetID, split notes, and all other new functionality.
  • Backward compatibility for Orchard Bundles

The proposed changes should be considered a draft, not a final version.

PaulLaux and others added 17 commits December 6, 2022 15:02
* Added .circleci/config.yml
Implements the issuer keys as

    IssuerAuthorizingKey -> isk
    IssuerVerifyingKey -> ik

Test vectors generated with zcash_test_vectors repo
* Added NoteType to Notes
* Added NoteType to value commitment derivation
* Circleci project setup (#1)

* Added .circleci/config.yml

* Added NoteType to Notes

* reformated file

* updated `derive` for NoteType

* added note_type to value commit derivation

* rustfmt

* updated ci config

* updated ci config

* updated ci config

* updated derive for note_type

* added test for arb note_type

* added test for `native` note type

* zsa-note-encryption: introduce AssetType and encode and decode it in note plaintexts

* zsa-note-encryption: extend the size of compact notes to include asset_type

* fixed clippy warrnings

* rustfmt

* zsa-note-encryption: document parsing requirement

* zsa-note-encryption: revert support of ZSA compact action

* zsa_value: add NoteType method is_native

* zsa-note-encryption: remove dependency on changes in the other crate

* zsa-note-encryption: extract memo of ZSA notes

* zsa-note-encryption: tests (zcash_test_vectors 77c73492)

* zsa-note-encryption: simplify roundtrip test

* zsa-note-encryption: more test vectors (zcash_test_vectors c10da464)

* Circleci project setup (#1)

* Added .circleci/config.yml

* issuer keys implementation (#5)

Implements the issuer keys as

    IssuerAuthorizingKey -> isk
    IssuerVerifyingKey -> ik

Test vectors generated with zcash_test_vectors repo

* Added NoteType to Notes (#2)

* Added NoteType to Notes
* Added NoteType to value commitment derivation

* zsa-note-encryption: use both native and ZSA in proptests

* zsa-note-encryption: test vector commit 51398c93

* zsa-note-encryption: fix after merge

Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com>
Co-authored-by: Paul <lauxpaul@protonmail.com>
Co-authored-by: Aurélien Nicolas <info@nau.re>
Co-authored-by: Daniel Benarroch <danielbenarroch92@gmail.com>
+ Updated test bsk_consistent_with_bvk to verify mixed note types.
+ Added NoteType support to the builder and the bundle.
+ added split_flag to SpentInfo and as input to the Circuit (currently commented out)
+ added conditional cv_sum calculation (currently commented out)
+ added padding to actions
- added IssueBundle and IssueAction
- added a builder for IssueBundle
- added verify_issue_bundle() for consensus verification.
- unit tests.
added tests in `tests/zsa.rs`
* disabled split notes and proof check for zsa transfer
* fixes and suggestions

* changed "issuer" to "issuance" as per zcash#356 (comment)

* terminology fixes

* updated naming
* rename 2 note_type -> asset as per  zcash#356 (comment)

* added a dedicated type for "IssuanceAuth"

* disabled codecov github action due to bad behavior. 

* extracted "is_asset_desc_of_valid_size()" into asset_id.rs
* improved `verify_issue_bundle()`
Added a method to add assets to burn to the Builder

bvk computation now includes the burnt assets

Added Tests for bsk/bvk consistency for burning

Added E2E tests for assets burning
Added CI badge to README
Added `OrchardDomainV3` on top of the encryption generalization (QED-it/librustzcash#18).

not for review: note_encryption.rs, note_encryptionv2v3.rs and src/test_vectors/note_encryption.rs. These files represent two possible approaches for backward compatibility and will be finalized down the road. (the files were excluded from the build).
@PaulLaux PaulLaux mentioned this pull request Jan 31, 2023
alexeykoren and others added 12 commits February 9, 2023 12:44
When split_flag is set, the following values are modified
* v_net is equal to -v_new instead of v_old - v_new
* cv_net is evaluated with this new value of v_net

The following constraints are modified
* (v_old - v_new = magnitude * sign) becomes (v_old * (1-split_flag) - v_new = magnitude * sign) to take into
   account the new value of v_net
* nf_old = nf_old_pub is only checked when split_flag=0
 * the new constraint asset_old = asset_new is always checked regardless of the value of split_flag
- Renamed AssetId to AssetBase
- Changed the  AssetBase implementation to support the zip update.
- Updated visibility for various members of issuance.rs
…#49)

This PR updates the test-vectors from the updates to the zcash-test-vectors repository (see here).

The keys test is also updated to now use the asset base from the test vectors instead of just using the native asset.
In the circuit, we update value_commit_orchard to take into account asset.
Previously, value_commit_orchard returns cv_net = [v_net] ValueCommitV + [rcv] ValueCommitR..
Now, value_commit_orchard returns cv_net = [v_net] asset + [rcv] ValueCommitR.
ValueCommitV and ValueCommitR are constants
v_net is equal to sign * magnitude where sign is in {-1, 1} and magnitude is an unsigned integer on 64 bits.

To evaluate [v_net] asset where v_net = sign * magnitude, we perform the following steps
1. verify that magnitude is on 64 bits
2. evaluate commitment=[magnitude]asset with the variable-base long-scalar multiplication
3. evaluate result=[sign]commitment with the new mul_sign gate
We would like to have a constant-time evaluation of the note commitment for both ZEC and ZSA.
ZEC_note_commitment=Extract_P(SinsemillaHashToPoint(zec_personalization, common_bits) + [rcm]R)
ZSA_note_commitment=Extract_P(SinsemillaHashToPoint(zsa_personalization, common_bits || asset) + [rcm]R)

R is the same constant for ZEC and ZSA note commitments.
1. Added a new error, `ValueSumOverflow`, that occurs if the sum value overflows when adding new supply amounts.
2. Created a new `supply_info` module containing `SupplyInfo` and `AssetSupply` structures, with `add_supply` function and unit tests for it.
3. Renamed the `are_note_asset_ids_derived_correctly` function to `verify_supply`, changed its behavior to verify and compute asset supply, added unit tests for it.
4. Updated the `verify_issue_bundle` function to use the changes mentioned above, updated its description, and added new unit tests.
5. Renamed errors with `...NoteType` suffix in the name to `...AssetBase`.
6.  Added `update_finalization_set` method to `SupplyInfo` and use after the calls of `verify_issue_bundle function` (if needed), instead of mutating the finalization set inside `verify_issue_bundle`.
- Add getter method for Bundle.burn field
For zcash_note_encryption, we have to use version 0.2 with QEDIT patch.
In the circuit, we update note_commit to take into account asset.
Previously, note_commit returns cm = hash(Q_ZEC, msg) + [rcm]R.
Now, note_commit returns
- cm = hash(Q_ZEC, msg) + [rcm]R for ZEC note
- cm = hash(Q_ZSA, msg || asset) + [rcm]R for ZSA note

We now evaluate note_commit with the following steps
1. evaluate **hash_zec = hash(Q_ZEC, msg)**
2. evaluate **hash_zsa = hash(Q_ZSA, msg || asset)**
3. select **hash = hash_zec if is_native_asset**
                         **= hash_zsa otherwise**
4. evaluate **cm = hash + [rcm]R**
5. check some constraints on msg and asset and their decompositions
6. return **cm**

The following modifications are required to update note_commit:
- add a is_native_asset witness (and check that it is a boolean and its
value is correct according to asset)
- add a MUX chip to evaluate a multiplexer on Pallas points

Warning: we increased the size of the Orchard circuit !
ConstanceBeguier and others added 19 commits April 24, 2025 13:52
Merge zcash/orchard (commit  fcb14de) into zsa1  with following modifications
- Update tests comparing orchard digest against a fixed value (the default memo value has been updated)
- Import the last version of generated test_vectors files (see QED-it/zcash-test-vectors#26)
- Fix clippy errors
- Expose (Extracted)NoteCommitment in public API
- Direct evaluation of note commitments (outside the circuit)
- Rename new_with_personalization by new_with_separate_domains
- A fixed size for asset_id
- Removed RTL chars to avoid confusing the text editor.
- Minor spacing fixes
Update compute_asset_desc_hash function
- Now accepts &NonEmpty<u8> instead of &[u8]
- Returns [u8; 32] directly (no longer wrapped in Result)
- Panics if asset_desc is not valid UTF-8

Update get_burn_tuple function
- Now takes asset_desc_hash as input instead of asset_desc
- Changes the function’s visibility to private

Cleanup unused code
- Removed unused errors: WrongAssetDescSize, InvalidAssetDescHashLength
- Removed unused constant: MAX_ASSET_DESCRIPTION_SIZE
- Removed unused function: is_asset_desc_of_valid_size
To use our latest version of zcash_note_encryption:
- Remove the version of zcash_note_encryption from Cargo.toml
- Update Cargo.lock
…ersions (#169)

### Why
proptest ≥ 1.5 wraps `rand_core::RngCore` in a new trait that also needs
`DerefMut`; `StdRng` lacks that, so the crate failed to compile after
`cargo update` (E0277 / E0599).

### What changed
* **proptest** pinned to **1.2.0** (last release before the API shift)  
* **font-kit 0.11.0** and **half 2.2.1** locked to keep MSRV 1.70
This PR removes generic type parameter from Orchard PCZT bundle
simplifying the flow in librustzcash
Update zcash_note_encryption crate
- Point to zcash/zcash_note_encryption repo
- Rename this crate to zcash_note_encryption instead of
zcash_note_encryption_zsa
We would like to remove circuit flag from commitment function. To do
that, we have to replace `OrchardFlavor` with `OrchardDomainCommon` in
`commitment` function and in `derive_bvk` function.
In librustzcash, we would like to use fake_compact_action function in
test.
OrchardFlavor modifications:
- Remove circuit_flavor field from Unproven struct
- Remove const FLAVOR from OrchardFlavor trait

OrchardCircuit modifications:
- Create ZsaAdditionalWitnesses struct.
- When creating witnesses from OrchardVanilla circuits, panic if the
asset is not the native asset or if split_flag is not false.

Other modifications:
- Reduce diff with upstream
- Remove some types to improve readability
### Background

* Orchard’s CI has a `build-latest` job that deletes `Cargo.lock` before
it builds, so it always picks the newest compatible crate versions.
* Everything went well until **proptest 1.7** was released. The next CI
run removed `Cargo.lock`; the resolver upgraded proptest to 1.7, which
depends on **`rand` 0.9**. Orchard and its crypto deps still use
**`rand` 0.8** interface, and the mixed `rand_core` versions broke the
build.
* PR #169 fixed Orchard by pinning **`proptest = 1.2.0`** (that was the
version in the old lockfile, known to work).

### Why that pin now breaks Zebra

* `zebra-chain` and `zebra-scan` declares **`proptest = "1.4"`**. With
an older Orchard commit (no exact pin) all crates (including `orchard`
and `librustzcash` crates) resolved to 1.4.x.
* Updating Zebra to the new Orchard commit brings in **`=1.2.0`**, and
Cargo can’t satisfy **both** `=1.2.0` and `^1.4.0`.

### What this PR changes

* Pin proptest to **1.4.0** in Orchard *and* librustzcash:

```toml
# Cargo.toml
proptest = { version = "=1.4.0", optional = true }

[dev-dependencies]
proptest = "=1.4.0"
```

* Version 1.4.0 is still on `rand` 0.8, so no further code changes are
needed in `orchardd` and it satisfies Zebra’s `1.4.0` constraint.

### A few summarization notes

1. **Why did `proptest = "1.0.0"` work and then fail?**  
The caret requirement means “any release ≥ 1.0.0 < 2.0.0”. Deleting
`Cargo.lock` let Cargo upgrade to the newest 1.y.z (now 1.7), which
brings in `rand` 0.9 and conflicts with the rest of the tree.

2. **Why list proptest in *both* `[dependencies]` and
`[dev-dependencies]`?**
- feature `test-dependencies` includes `proptest` and `proptest` must be
an optional dependency;
   - `dev-dependencies` are not allowed to be optional.
)

### Context

* The last change (#175) fixed a Zebra version clash by pinning
`proptest` to **1.4.0**.
* That exact pin conflicts with **librustzcash**’s `cargo-vet` policy,
which has an exemption only for **1.2.0**.
* Orchard is actually compatible with every 1.x release up to—but not
including—1.7 (1.7 introduces the `rand` 0.9 break).

### What this PR does

* **Cargo.toml** now allows any `proptest` version **≥ 1.0.0 and <
1.7.0**.
* **Cargo.lock** is rolled back to the version that existed before PR
#175 (uses `proptest` 1.2.0).
- Rename OrchardCommonDomain to OrchardPrimitives
- Rename domain folder to primitives
- Replace OrchardFlavor with OrchardCircuit or OrchardPrimitives whenever possible
- Update comments
- Reduce diff with upstream
- Unify Rust version to 1.71 (Cargo.toml, README.md and
rust-toolchain.toml)
- Remove pinned version for half and font-kit in Cargo.toml
- Remove public unsplittable function
- Clean tests/zsa.rs by creating one Merkle tree with all notes and by
generating new keys to avoid using the same address for both sender and
recipient in bundles
- Simplify `IssueAction::verify(...)` by moving the
`AssetBaseCannotBeIdentityPoint` check outside the loop.
- Rationale: Previously we checked that for each note, its asset is not
equal to identity point and for each note, its asset is equal to the
issue asset. Now we checked that the issue asset is not equal to the
identity point and for each note, its asset is equal to the issue asset.
Those two versions will fail in the same cases.
- We removed `action_verify_invalid_for_asset_base_as_identity`,
`issue_bundle_cannot_be_signed_with_asset_base_identity_point` and
`issue_bundle_verify_fail_asset_base_identity_point` tests because it is
now very difficult to create a test for this case. To create a test for
this case, we have to choose an `ik` and an `asset_desc_hash` such that
the `AssetBase` derived from them is equal to the identity point.
Constant value does not need prop_compose function.
Cargo.toml Outdated
poseidon = { package = "halo2_poseidon", version = "0.1" }
serde = { version = "1.0", default-features = false, features = ["derive"] }
sinsemilla = "0.1"
sinsemilla = { git = "https://github.com/zcash/sinsemilla", rev = "aabb707e862bc3d7b803c77d14e5a771bcee3e8c" }
Copy link
Contributor

Choose a reason for hiding this comment

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

These dependency bumps should be done via [patch.crates-io] directives.

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

@PaulLaux PaulLaux changed the title Orchard-ZSA reference implementation OrchardZSA reference implementation Aug 22, 2025
ConstanceBeguier and others added 7 commits August 26, 2025 10:08
Update `verify_issue_bundle` to return `IncorrectRhoDerivation` when the
rho value of an issuance note is incorrect.
The `verify_issue_bundle` function now requires `first_nullifier` as an
input parameter.
…es (#182)

This PR makes the updates to the encoding of the issuance validating key
and the issuance authorization signature, as done in the specification
in zcash/zips#1042, along with the further updates in zcash/zips#1048
and zcash/zips#1053.

The test vectors are updated in QED-it/zcash-test-vectors#31.

---------

Co-authored-by: Constance Beguier <constance@qed-it.com>
Change the parameter name in methods `try_sign` and `verify` from `msg` to `sighash`.
This clarifies that the input must be a finalized digest.
Add `SighashVersion` (version and associated data) to
- Orchard binding signatures,
- Orchard authorizing signatures, and
- issuance authorization signatures.

Update `auth_digest` by adding `SighashVersion`
Modifications in upstream from last merge
- Merge pull request zcash#470 from QED-it/compatible_with_zsa_halo2
- Update Cargo.toml by moving some modifications into
`[patch.crates-io]` section
- Remove `spec/prf_expand.rs` file (we forget to remove it during a
merge with upstream)
- Remove `conditionally_negate` and `check_structural_validity`
functions (there are only used once)
- Remove `map_proof` function on `Bundle<InProgress>` (it is not used in
any QEDIT repos)
- Move some imports
- Add review hint comments
@PaulLaux PaulLaux closed this Sep 9, 2025
@PaulLaux
Copy link
Author

continued in #471

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.

8 participants