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

Update to upstream (zcash/main v0.8.0) #103

Merged
merged 72 commits into from
May 9, 2024
Merged

Update to upstream (zcash/main v0.8.0) #103

merged 72 commits into from
May 9, 2024

Conversation

dmidem
Copy link

@dmidem dmidem commented Apr 25, 2024

This PR merges the latest updates from the zcash/orchard repository (version 0.8.0) into zsa1 branch. These updates include refactorings and enhancements which are detailed below. The integration has been completed in the zsa1-with-zcash-0.8.0 branch, where conflicts were resolved and all unit tests and CI checks pass successfully.

Key Changes from zcash/orchard v0.8.0

  1. BundleType enum introduced: Replaces direct use of bundle flags.
  2. Recipient renamed to Output: Updates type and function names accordingly.
  3. New type Rho: Used for variables with rho value, keeping Nullifier for nullifiers.
  4. External crate zip32 added and used: Contains parts of local zip32 module functionality and new features, while local zsa32 retains orchard-specific features now.
  5. Refactoring of Builder::build function: Logic moved to new bundle function, introducing BundleMetadata to track indices pre-shuffle.

defuse and others added 30 commits July 21, 2022 14:39
`reddsa 0.5.1` has MSRV 1.65.
This is currently "whatever lockfile happened to last work for str4d",
but going forward will be the lockfile we use for testing our MSRV. See
https://blog.rust-lang.org/2023/08/29/committing-lockfiles for rationale
on this change.
The term `recipient` is commonly used to refer to the address to which a
note is sent; however, a bundle may include multiple outputs to the same
recipient. This change is intended to clarify this usage.

Co-authored-by: Daira Emma Hopwood <[email protected]>
Add a public bundle-builder function as an alternative to the mutable builder.
Signed-off-by: Daira Emma Hopwood <[email protected]>
Change license from BOSL to "MIT OR Apache-2.0"
The changelog changes in zcash#362 had a non-merge conflict with zcash#363,
because zcash#362 was implemented as if it would be part of the 0.3.0
release but was in fact merged just afterwards.

fixes zcash#391

Signed-off-by: Daira Emma Hopwood <[email protected]>
Move some changelog entries from 0.3.0 to 0.4.0
…duced.

This adds a flag to `BundleType` that, when set, requires a dummy-only
bundle to be produced even if no spends or outputs are added to the
builder, and when unset results in standard padding.
Modify `BundleType` to exclude the anchor & allow no bundle to be produced.
Make the `MERKLE_DEPTH_ORCHARD` constant public.
In order to be able to associate requested spends and outputs with the
indices of the actions that execute these operations, it is necessary to
track the randomization of inputs and outputs and return the mappings
that resulted from that shuffling.
str4d and others added 20 commits February 26, 2024 18:05
Trivial update to the doc for `struct Action`
Additions needed for Orchard batch scanning
…horchard

Add a `MerkleHashOrchard::random` function under the `test-dependencies` feature.
This change removes the ability to construct a `Rho` value directly from
the public API, except via deserialization from bytes (which is
necessary in order to be able to serialize a `Note`). Ordinarily, `Rho`
should be obtained either from an already-constructed `Note` or from an
`Action` or `CompactAction`.
Add a `Rho` type, to distinguish from revealed nullifiers of spent notes.
Add `impl Distribution<MerkleHashOrchard> for Standard` for testing.
…uble column in the use of external zip32 crate
@QED-it QED-it deleted a comment from what-the-diff bot Apr 30, 2024
@dmidem dmidem requested a review from PaulLaux April 30, 2024 10:55
Copy link
Collaborator

@PaulLaux PaulLaux left a comment

Choose a reason for hiding this comment

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

Good overall, some more polish for clarity is required

src/builder.rs Outdated
bundle_required: false,
};

/// The DISABLED bundle type does not permit any bundle to be produced, and when used in the
/// builder will prevent any spends or outputs from being added.
pub const DISABLED: BundleType = BundleType::Transactional {
flags: Flags::from_parts(false, false, false), // FIXME: is this correct?
flags: Flags::from_parts(false, false, false), // FIXME: is `false` value for ZSA flag correct here?
Copy link
Collaborator

Choose a reason for hiding this comment

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

yes

Copy link
Author

@dmidem dmidem May 1, 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.

And there're similar questions for bundle.rs: does zsa_enabled need to be false for SPENDS_DISABLED and OUTPUTS_DISABLED?

builder.rs:106:

    /// The flag set with spends disabled.
    pub const SPENDS_DISABLED: Flags = Flags {
        spends_enabled: false,
        outputs_enabled: true,
        zsa_enabled: false, // FIXME: is this correct?
    };

    /// The flag set with outputs disabled.
    pub const OUTPUTS_DISABLED: Flags = Flags {
        spends_enabled: true,
        outputs_enabled: false,
        zsa_enabled: false, // FIXME: is this correct?
    };

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes, both are correct, the first is used for mining zec, the second is not used.

Copy link
Author

Choose a reason for hiding this comment

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

Got it, thanks. Fixed (removed FIXME comments).

src/builder.rs Outdated
let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng);
hm.insert(
dummy_spend.note.asset(),
(vec![(usize::MAX, dummy_spend)], vec![]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

why usize:MAX?

Copy link
Collaborator

Choose a reason for hiding this comment

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

see below

Copy link
Author

Choose a reason for hiding this comment

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

Dummy spends/outputs should not participate in BundleMetadata indexing. To manage this, we need a way to mark them as a dummy in the indexed vectors of spends/outputs, so that in further code of bundle functions the following assignments will be skipped:

bundle_meta.spend_indices[spend_idx] = action_idx;
bundle_meta.output_indices[out_idx] = action_idx;

In the previous version of the code for this PR I simply used usize::MAX instead of the indices for marking dummy spends/outputs, so the checks:

if spend_idx < num_requested_spends {
if out_idx < num_requested_outputs {

skipped such items.

I agree that it was confusing, so now, I use the Option type to mark dummy items (for dummy items the index is None, for real ones - Some(...))

Copy link
Collaborator

Choose a reason for hiding this comment

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

nice, lets add comment

if hm.is_empty() {
        let dummy_spend = pad_spend(None, AssetBase::native(), rng);
        // dummy_spend should not be included in the indexing and marked as None.
        hm.insert(
            dummy_spend.note.asset(),
            (vec![(None, dummy_spend)], vec![]),
        );

Copy link
Author

Choose a reason for hiding this comment

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

Fixed (added the comment).

src/builder.rs Outdated
@@ -621,7 +620,7 @@ impl Builder {
///
/// The returned bundle will have no proof or signatures; these can be applied with
/// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively.
pub fn build<V: TryFrom<i64>>(
pub fn build<V: Copy + Into<i64> + TryFrom<i64>>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

why Copy + Into ?

Copy link
Collaborator

@PaulLaux PaulLaux May 1, 2024

Choose a reason for hiding this comment

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

previously we worked hard to avoid it + see comment below

Copy link
Author

@dmidem dmidem May 7, 2024

Choose a reason for hiding this comment

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

The Copy + Into<i64> constraint was added to the build function's signature in PR #35 of the QED-it/orchard repository.

The reason for this, as I understand it, is that in the Zcash repository, the bvk value was calculated separately within the build function instead of using the bundle.binding_validating_key() method (this method requires the Copy + Into<i64> constraint).

PR #35 added the burn functionality, making the separate calculation of bvk in build more complicated. To avoid duplicating code, the calculation was switched to use bundle.binding_validating_key(), which required the Copy + Into<i64> constraint.

Now, to fix this and remove the Copy + Into<i64> constraint while still using bundle.binding_validating_key() (and avoiding code duplication), I suggest calculating native_value_balance as an i64 first, then converting it to V, which doesn't require Into<i64>. Also, to reuse the binding_validating_key logic for bvk, we could modify it by adding a new free function called derive_bvk in the bundle.rs module. This function would take three parameters: an actions iterator, a generic value_balance, and a burn iterator. Using iterators would avoid extra memory usage.

We can call derive_bvk from binding_validating_key, and have bundle call derive_bvk instead of directly using binding_validating_key.

I've implemented this solution in the latest version of the code for this PR.

src/builder.rs Outdated
Comment on lines 663 to 666
let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng);
hm.insert(
dummy_spend.note.asset(),
(vec![(usize::MAX, dummy_spend)], vec![]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't like the potential duplicated logic, can we use pad_spend() for this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

instead SpendInfo::dummy(AssetBase::native(), rng);

Copy link
Author

Choose a reason for hiding this comment

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

Fixed it in this way:

let dummy_spend = pad_spend(None, AssetBase::native(), rng);

src/builder.rs Outdated
Comment on lines 741 to 742
.chain(iter::repeat_with(|| {
(usize::MAX, pad_spend(first_spend.as_ref(), asset, &mut rng))
Copy link
Collaborator

Choose a reason for hiding this comment

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

usize::MAX is unintuitive, use named var / constant (everywhere)
reading the code I need to understand at this point that this is the spend index but currently it is unclear
also unclear how multiple spends can have the same index (usize:max)

Copy link
Author

@dmidem dmidem May 2, 2024

Choose a reason for hiding this comment

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

Fixed (now it uses the Option type to mark dummy spends/outputs to skip them when populating BundleMetadata, see the comment above).

dmidem added 4 commits May 1, 2024 22:00
…nction. 2) Refactor builder::bundle function (pre-action genetation), to split 'fold' into three parts
- Introduce `derive_bvk` function for streamlined calculation of `bvk`
- Use `derive_bvk` in `bundle.binding_validating_key()` to avoid duplication
- Adjust `native_value_balance` calculation to an `i64` and convert to `V`
- Optimize calculations with iterators to reduce memory usage
Copy link
Collaborator

@PaulLaux PaulLaux left a comment

Choose a reason for hiding this comment

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

one more refactor is required for clarity.
Also, see 2 answers for previous questions.

src/builder.rs Outdated
Comment on lines 640 to 651
#[allow(clippy::type_complexity)]
fn partition_by_asset(
spends: &[SpendInfo],
recipients: &[RecipientInfo],
outputs: &[OutputInfo],
rng: &mut impl RngCore,
) -> HashMap<AssetBase, (Vec<SpendInfo>, Vec<RecipientInfo>)> {
) -> HashMap<
AssetBase,
(
Vec<(Option<usize>, SpendInfo)>,
Vec<(Option<usize>, OutputInfo)>,
),
> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's add a named type to explain the logic.
let's switch location between the content and the index SpendInfo <-> MetadataIdx

/// The index of the attached spend or output in the bundle.
/// None indicates a dummy note.
/// The index is used to track the position of the note in the bundle.
type MetadataIdx = Option<usize>;

/// Partition a list of spends and recipients by note types.
/// Method creates single dummy ZEC note if spends and recipients are both empty.
#[allow(clippy::type_complexity)]
fn partition_by_asset(
    spends: &[SpendInfo],
    outputs: &[OutputInfo],
    rng: &mut impl RngCore,
) -> HashMap<
    AssetBase,
    (
        Vec<(SpendInfo, MetadataIdx)>,
        Vec<(OutputInfo, MetadataIdx)>,
    ),
> {

Copy link
Author

Choose a reason for hiding this comment

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

Done.

@dmidem dmidem merged commit 78c8efc into zsa1 May 9, 2024
28 checks passed
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.

6 participants