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

use .reverse() + do same for public calls + unit tests #1023

Closed
wants to merge 1 commit into from

Conversation

rahul-kothari
Copy link
Contributor

Description

Stack is basically a queue in a reverse order. So doing what santiago originally did but adding a .reverse() would work.
Added some tests

Please sanity check that the ordering I have written in the tests are similar to what you would expect from ACVM or kernel

Checklist:

  • I have reviewed my diff in github, line by line.
  • Every change is related to the PR description.
  • I have linked this pull request to the issue(s) that it resolves.
  • There are no unexpected formatting changes, superfluous debug logs, or commented-out code.
  • The branch has been merged or rebased against the head of its merge target.
  • I'm happy for the PR to be merged at the reviewer's next convenience.

Copy link
Collaborator

@spalladino spalladino left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this! There's a change I think it's worth making before merging though.

}
return logs;
// without the .reverse(), the logs will be in a queue like fashion which is wrong as the kernel processes it like a stack.
return [execResult.encryptedLogs, ...execResult.nestedExecutions.reverse().flatMap(collectEncryptedLogs)];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Javascript's native reverse is evil af (as most js methods), since it both reverses in place and returns a reference to the reversed array. So, every time you're calling collectEncryptedLogs, you're inadvertently reversing all nested executions.

> a = [1,2,3]
[ 1, 2, 3 ]
> a.reverse()
[ 3, 2, 1 ]
> a
[ 3, 2, 1 ]

Better make a copy of the array before reversing it, like:

  return [execResult.encryptedLogs, ...[...execResult.nestedExecutions].reverse().flatMap(collectEncryptedLogs)];

Copy link
Contributor Author

Choose a reason for hiding this comment

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

holy mother of god that makes sense - thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

holy mother of god

That's the typical reaction of every developer when faced with js. Reminded me of this "oh-no js" moment I had a while back.

|---------->fnE (log5)
|-------->fnF (log6)
|-------->fnG (log7)
Circuits and ACVM process in a DFS + stack like format: [fnA, fnE, fnF, fnG fnC, fnD, fnB]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
Circuits and ACVM process in a DFS + stack like format: [fnA, fnE, fnF, fnG fnC, fnD, fnB]
Circuits and ACVM process in a DFS + stack like format: [fnA, fnE, fnG, fnF fnC, fnD, fnB]

At least that's what I understand from the yarn-project/aztec-rpc/src/kernel_prover/kernel_prover.ts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup you are right - in fact the test also returns that - forgot to write my comment correctly thanks!

Copy link
Contributor

@jeanmon jeanmon left a comment

Choose a reason for hiding this comment

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

Great job!
Please address my litlle suggestion.

fnA ()
|----------> fnB () -> fnC ()
|----------> fnD () -> fnE ()
Circuits and ACVM process in a DFS + stack like format: [fnA, fnB, fnC]
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Circuits and ACVM process in a DFS + stack like format: [fnA, fnB, fnC]
Circuits and ACVM process in a DFS + stack like format: [fnA, fnD, fnE, fnB, fnC]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah good catch!

@rahul-kothari rahul-kothari deleted the rk/clean_collect_logs branch July 11, 2023 17:19
@rahul-kothari
Copy link
Contributor Author

ah just realised I need to push to master as opposed to my other branch

lucasxia01 added a commit that referenced this pull request Oct 29, 2024
eccvm_recursive_verifier_test measurements (size-512 eccvm recursive
verification)

Old: 876,214
New: 678,751

The relative performance delta should be much greater for large eccvm
instances as this PR removes an nlogn algorithm.

This PR resolves issue
[#857](AztecProtocol/barretenberg#857) and
issue [#1023](AztecProtocol/barretenberg#1023)
(single batch mul in IPA)

Re: [#1023](AztecProtocol/barretenberg#1023).
The code still performs 2 batch muls, but all additional * operator
calls have been combined into the batch muls.

It is not worth combining both batch muls, as it would require a
multiplication operation on a large number of scalar multipliers. In the
recursive setting the scalars are bigfield elements - the extra
bigfield::operator* cost is not worth combining both batch_mul calls.

Additional improvements:

removed unneccessary uses of `pow` operator in ipa - in the recursive
setting these were stdlib::bigfield::pow calls and very expensive

removed the number of distinct multiplication calls in
ipa::reduce_verify_internal

cycle_scalar::cycle_scalar(stdlib::bigfield) constructor now more
optimally constructs a cycle_scalar out of a bigfield element. New
method leverages the fact that `scalar.lo` and `scalar.hi` are
implicitly range-constrained to remove reundant bigfield constructor
calls and arithmetic calls, and the process of performing a scalar
multiplication applies a modular reduction to the imput, which makes the
explicit call to `validate_scalar_is_in_field` unneccessary

---------
Co-authored-by: lucasxia01 <[email protected]>
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.

3 participants