-
Notifications
You must be signed in to change notification settings - Fork 39
Orchard-ZSA reference implementation #372
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
base: main
Are you sure you want to change the base?
Conversation
* 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 <[email protected]> Co-authored-by: Paul <[email protected]> Co-authored-by: Aurélien Nicolas <[email protected]> Co-authored-by: Daniel Benarroch <[email protected]>
+ 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).
Make IVK::from_bytes public
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 !
… functions (#138) This PR modifies the `verify_issue_bundle` function and refactors the `supply_info.rs` module by removing `SupplyInfo` and introducing a new generic type, `AssetInfo`, in place of the previous `AssetSupply` struct. `AssetInfo` allows to properly distinguish the asset verification logic between reference notes required for first issuances versus optional references for subsequent issuances. #### Key Changes 1. **Rename `AssetSupply` struct to `AssetInfo`** 2. **Rename `IssueAction::verify_supply` to `IssueAction::verify` and update its return value** - The `verify` method now returns only the sum of the action's note values instead of `AssetInfo`. - The `is_finalized` and `reference_note` action properties are now handled directly in the `verify_issue_bundle` function. 3. **Revise `verify_issue_bundle`** - Modifies the function signature to use a `get_global_asset_state` callback instead of relying on a `finalization` set. - Changes the return type to a `HashMap<AssetBase, AssetInfo>` (instead of `SupplyInfo`). - Updates the function so that a reference note is mandatory for the first appearance of any asset. Tests and documentation have been updated accordingly. 4. **Remove `supply_info.rs`** - Deletes the `SupplyInfo` struct and related tests, since `verify_issue_bundle` now returns a `HashMap` of `AssetInfo` objects. 5. **Test updates** - Revises tests to align with the new `verify_issue_bundle` signature and the `get_global_asset_state` approach. 6. **Add issuance workflow test** - Adds a new test `issue_bundle_verify_with_global_state` that performs a series of bundle creations and verifications, with a global state simulation. 7. **Miscellaneous fixes** - Simplifies `Error` variant imports in `issuance.rs` by referencing the local `Error` enum directly.
This PR extends the derives for orchard protocol marker types ("flavors") by adding `PartialEq` and `Eq` to `OrchardVanilla` and `OrchardZSA`. This is needed to reuse these marker types directly in Zebra without introducing duplicated types.
- Added std and circuit features to ZSA - Replaced HashMap/HashSet with BTreeMap/BTreeSet (required implementing ordering for AssetBase) - Added ZSA fields to PCZT structures - Upgraded Rust to version 1.70.0 (done in a later commit on zcash/orchard) - Replaced all std imports - Implemented regression tests using fixed bundle outputs to verify backward compatibility with zcash/orchard repo
pub struct Bundle<A: Authorization, V, D: OrchardDomainCommon> { | ||
/// The list of actions that make up this bundle. | ||
actions: NonEmpty<Action<T::SpendAuth>>, | ||
actions: NonEmpty<Action<A::SpendAuth, D>>, | ||
/// 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: T, | ||
authorization: A, | ||
} |
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.
@str4d and I had an extensive discussion about this type in a pairing. Our conclusion is that parameterizing the Bundle
type via the D
parameter causes the downstream code that consumes Orchard bundles to be exposed to details about note encryption that are too low-level for the consumer. Also, the fact that we are parameterizing with D
but are not fully concretizing the contents of the bundle relative to that parameter enables the representation of mixed states (e.g. D = OrchardVanilla
but with burn
nonempty) that we do not want to exist.
Instead, there should be separate Bundle
and BundleZsa
types; this then means that:
- the
OrchardDomainCommon
type may not need to exist, and we can use separate implementations ofzcash_note_encryption::Domain
. - the new fields,
expiry_height
andburn
will only exist in theBundleZsa
type.
The Action
type then doesn't need to be parameterized by the domain type; it can just be parameterized by the type of the enc_ciphertext
, and each Bundle
type can concretely set this to a ciphertext type that directly matches what is used in the domain. This will facilitate the memo changes from ZIP 231 (for which the concrete length will be different than at present, and for which zcash_note_encryption::Domain::Memo
will be set to the type of the memo key.)
At the top level, what we will do is route scanning of V6 transaction outputs into one batch decryptor, and scanning of V5 outputs into a separate batch decryption.
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.
Actually, having the parameter D
does not expose much detail to the downstream consumer (unless explicitly requested).
The consumer have either
let bundle: Bundle<_, _, Orcahrd> = ...
Or
let bundle: Bundle<_, _, OrcahrdZSA> = ...
and can proceed with the Bundle<_>
operations. But this almost never happens since most of the handling is unified. (We have it mostly in tests.)
The major consideration for this type of parametrization is clean code reuse: in most cases Bundle<_,_,Orchard>
and Bundle<_,_,OrchardZSA>
are treated the same and we can have nice abstraction in the form of
let bundle: Bundle<_, i64, D> = builder.build(rng);
bundle
.create_proof(&pk, rng)
.unwrap()
.apply_signatures(rng, [0; 32], &[])
.unwrap()
In critical places like
pub fn build<V: TryFrom<i64>, D: OrchardFlavor>(
self,
rng: impl RngCore,
) -> Result<Bundle<InProgress<Unproven, Unauthorized>, V, D>, BundleMetadata), BuildError> {
or
pub fn prepare<R: RngCore + CryptoRng>(
self,
mut rng: R,
sighash: [u8; 32],
) -> Bundle<InProgress<P, PartiallyAuthorized>, V, D> {
or
pub fn apply_signatures<R: RngCore + CryptoRng>(
self,
mut rng: R,
sighash: [u8; 32],
signing_keys: &[SpendAuthorizingKey],
) -> Result<Bundle<Authorized, V, D>, BuildError> {
among many others.
Later it is propogated Action
:
fn build<D: OrchardDomainCommon>(
self,
mut rng: impl RngCore,
) -> (Action<SigningMetadata, D>, Witnesses) {
Where also most of the logic is shared between an Orchard action and an OrchardZSA action.
All while the difference between the Bundles or the Actions is encapsulated inside OrchardFlavor
and called transparently by the consumers.
All while fully supporting backward compatibility.
Removing the parameter D
and creating two different types will obliterate all these nice properties, and the code will be harder to maintain and harder to reason about, as most of the logic for both is the same.
That being said, we can change the handling for the note encryption part to align with ZIP 231 once it is done and we can have it (or we can do it on top).
Also, the burn handling can be changed to have a dedicated empty type for Orchard
and non-empty type for OrchardZSA
as we did for Zebra's ShieldedData
:
pub struct ShieldedData<FL: Flavor> {
...
/// Assets intended for burning
/// Denoted as `vAssetBurn` in the spec (ZIP 230).
pub burn: FL::BurnType,
}
Forcing the burn to be empty for Orchard.
Other solutions for Burn and note encryption are also possible.
However, we strongly recommend keeping the D
parameter for Bundle
for the reasons mentioned above.
Commitment structure is reorganized to reflect the change in location of burn field --------- Co-authored-by: Vivek Arte <[email protected]>
724e98a
to
190a50c
Compare
A redo of #146 Merge zcash/orchard up to commit 4fa6d3b into zsa1 with following modifications - Added std and circuit features to ZSA - Replaced HashMap/HashSet with BTreeMap/BTreeSet (required implementing ordering for AssetBase) - Added ZSA fields to PCZT structures - Upgraded Rust to version 1.71.0 (done in a later commit on zcash/orchard) - Replaced all std imports - Implemented regression tests using fixed bundle outputs to verify backward compatibility with zcash/orchard repo
Reduced CI time.
Due to a change in the default memo, the output of orchard_digest changed.
…HARD_ISSUANCE_PERSONALIZATION
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
This PR implements draft ZIP 226 (Transfer and Burn of Zcash Shielded Assets) and draft ZIP 227 (Issuance of Zcash Shielded Assets).
burn
field inside the Orchardbundle
and the ability to utilize it. In addition the changes tobvk
andbsk
to support this change. See ZSA burn functionality QED-it/orchard#35 for a full list of changes.Domain
trait in thezcash_note_encryption
crate to support various lengths forCOMPACT_NOTE_SIZE
by converting the relevant constants into trait-specific types. Later, implementedOrchardDomainV3
to support the new note structure.zsa1
branch for details.Also included:
note_type
was renamed toasset
of typeassetID
.AssetID
derivation AssetID test vectors QED-it/orchard#34AssetID
, split notes, and all other new functionality.Orchard
BundlesThe proposed changes should be considered a draft, not a final version.