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

Saving scalar multiplications while computing 'UVKZGPCSCommitment' #216

Merged
merged 1 commit into from
Jan 3, 2024

Conversation

storojs72
Copy link
Contributor

Fixes #184

We exploit the fact that batched_lifted_degree_quotient (link) computes q_hat with the first half of the coefficients equal to zero. During subsequent MSM computation in UVKZGPCS::commit (link), zero coefficients of q_hat, which act as a scalars have no impact on the final value of 'UVKZGPCSCommitment'.

Two alternative implementations of UVKZGPCS::commit are actually proposed:

  • UVKZGPCS::commit_offset - uses additional offset that points to the first non-zero value among scalars (and same offset is used to skip non-relevant bases)
  • UVKZGPCS::commit_filter - uses specific preprocessing that excludes all non-zero values from scalars (and correspondent values from bases). It replaces the UVKZGPCS::commit in ZMPCS::open while q_hat_comm computing to save some scalar multiplications.

@huitseeker, I remember that you didn't support the filtering approach while our discussion, so I left it unused in actual execution of ZMPCS::open but it is still there - since I believe that we in theory can have a situation, when scalars passed to MSM may have a lot of zero values not necessarily in the beginning of the slice (which is the case), but scattered randomly. If it is not a viable assumption, we can remove it.

@storojs72 storojs72 force-pushed the issue-184 branch 2 times, most recently from f5b4816 to f93838f Compare December 22, 2023 17:39
@adr1anh
Copy link
Contributor

adr1anh commented Jan 2, 2024

I think for the context of this PR, commit_offset seems to be the most straight-forward for this use case.

Regarding the filtering approach, I think we would need some more experimentation to evaluate the performance. I'm fine with leaving the code in even if it unused for now.

Copy link
Contributor

@huitseeker huitseeker left a comment

Choose a reason for hiding this comment

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

The code looks fine on both the commit_offset and commit_filter approaches.

  • This is a bit out of scope for this PR, but I think we'll need something like commit_filter (irrespective of me not liking having to do this) across the code base, modifying the vartime_scalar_mul here and there,
  • but before we commit to commit_filter replacing the MSM, I would like to see benchmarks (perhaps rebased on Test vectors & benchmark for PCS #222), showing that replacement does not decrease performance (e.g. through memory allocation),
  • in the meantime the commit_offset is certainly a valid improvement, and will remain so, so I'm inclined to approve a change that focuses on that today: it clearly shows our data structure representation for q_hat is too big, and reduces it to size 1 << (num_vars - 1) from 1 << num_vars 🎉 1
  • however I am not sure it reaps all the benefits, reading the paper p.38 2:

The prover computes a $G_1$ Multi-Scalar Multiplication (MSM) of size $2^k$ for each commitment $C_k$. It also computes an MSM of size $N/2$ to commit to $\hat{q}$ as the latter has at most $N/2 - 1$ non-zero coefficients between degree $2^{n-1} - 1 = 2^n - d_{n-1} - 1$ and degree $2^n - 1$.

  • note: I don't think the zeros within that degree range $[2^{n-1} - 1, 2^n - 1]$ are expected to be consecutive, if N != 2^n
  • any cost reduction in committing to q_hat due to sparsity is expected to be yielded by the filtering optimization above whenever it's available anyway.

=> Requesting changes for a PR that focuses on commit_offset (great bug fix, thank you so much @storojs72 !)

Footnotes

  1. see my inline note about the intermediary offset variable: its value is never less than 1 << (num_vars - 1)

  2. in this context, n = num_vars

@@ -378,6 +379,7 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
})
.collect::<Vec<F>>();

let mut offset = 0;
Copy link
Contributor

@huitseeker huitseeker Jan 2, 2024

Choose a reason for hiding this comment

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

in this code block:

  • we can replace q_hat.len() by 1 << num_vars, this quantity does not change,
  • we can notice that as we go through the loop, offset moves from 1 << num_vars to 1 << num_vars - (1 << (num_vars - 1)) == 1 << (num_vars - 1) and directly output the final offset result rather than use a mutable variable to represent that

Copy link
Contributor Author

@storojs72 storojs72 Jan 3, 2024

Choose a reason for hiding this comment

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

Thanks, I think I have added necessary changes in fce367e and 9780554

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: the mut offset at the beginning is not very useful, as that usize is stack allocated - we may want to revert to the original, which declared offset as a local variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, thanks. I've realised it recently (f5f0edd)

@winston-h-zhang
Copy link
Contributor

I will be opening up another branch/PR to further explore how commit_filter can be implemented

@storojs72 storojs72 force-pushed the issue-184 branch 2 times, most recently from 21ab251 to 5cf9186 Compare January 3, 2024 13:25
@storojs72 storojs72 requested a review from huitseeker January 3, 2024 13:28
@@ -378,6 +379,7 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
})
.collect::<Vec<F>>();

let mut offset = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: the mut offset at the beginning is not very useful, as that usize is stack allocated - we may want to revert to the original, which declared offset as a local variable.

Comment on lines 263 to 264
#[allow(dead_code)]
pub fn commit_filtered(
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be good to move this function to the test module of non_hiding_zeromorph, or at least make it pub (in crate::provider) and #[cfg(test)]

@@ -801,4 +811,47 @@ mod test {
assert_eq!(zeta_x_scalars[k], scalar);
}
}

fn test_various_uvkzpcs_commit_template<E>() -> Result<(), NovaError>
Copy link
Contributor

Choose a reason for hiding this comment

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

This would benefit from a rename to test_ZM_commit_sparsity_template, which makes the goal of the test clear.

Comment on lines 256 to 257
&scalars[(offset)..],
&bases[(offset)..scalars.len()],
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I don't think you need the parentheses.

Copy link
Contributor

@huitseeker huitseeker left a comment

Choose a reason for hiding this comment

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

Excellent, thanks a ton @storojs72!

@storojs72 storojs72 added this pull request to the merge queue Jan 3, 2024
Merged via the queue into dev with commit d8008c3 Jan 3, 2024
7 checks passed
@storojs72 storojs72 deleted the issue-184 branch January 3, 2024 14:23
@huitseeker huitseeker mentioned this pull request Jan 3, 2024
1 task
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.

Zeromorph: shrink the q_hat commitments to size N/2
4 participants