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

New architecture for template generator #5

Merged
merged 54 commits into from
Jun 15, 2020

Conversation

ggutoski
Copy link
Contributor

@ggutoski ggutoski commented Jun 3, 2020

Why?

It is now much easier to automatically compute constants required for code generation from within gurvy instead of manually copy-pasting from sage. (Also, I did some house cleaning. There's still lots more cleaning needed though.)

The flagship example is the methods MulByNonResiduexPowery found in frobenius.go for each curve. Another example is the inverse of 2 modulo p used in curves with a field tower of the form used by BLS12-381, BW6-761. There are several other constants whose computation could also be automated in this way.

In the future, it will be easier to add new constants or new curves to gurvy. Perhaps one could even use this new architecture to reduce reliance on sage to make tests, though I suspect the complete elimination of sage from the process is not yet worth the effort.

Overview

Prior to this PR, all code (goff, tower, curve groups, pairing) for each curve was generated from a single executable invoked from the root directory via go generate ./internal/.... This single executable prevented the use of code generated earlier in the process to generate subsequent code. For example, it was not possible to use code from goff or the field tower to generate code for the pairing. Thus, it was impossible, for example, to automate the computation of constants used in Frobenius computations. Instead, these constants must be computed manually in sage and copy-pasted into gurvy's Go codebase.

By contrast, the new architecture splits code generation into four worker executables: one for each of goff, tower, curve groups, pairing. These four workers are managed by another master executable, so the original user-facing terminal command is the same: all code is generated with a single command:

go generate ./internal/...

Each worker is invoked under-the-hood via go run, which automatically compiles the executable from source before executing. Some of that source is generated by previous workers, so newly generated code is instantly compiled into the next worker's executable.

The new architecture

  • The master executable is located at /internal/generators/main.go. It contains all the info required to generate all the curves.
  • Instead of passing all this info to the four worker executables via terminal arguments, the master executable generates code in the curve package.
  • The four worker packages are primefields, tower, gpoint, and pairing. Each imports from curve---that's how they get their arguments.
  • A minimalist package has at least two files:
     ├── generator.go
     └── main
         └── main.go
    
    Template execution occurs in generator.go. The master executable invokes main/main.go via go run. main.go is typically just a wrapper that imports curve (as a way to get curve info) and invokes generator.go.
    • The primefields worker has this simple structure. All the work is done by goff, so no more code is needed here.
  • All workers other than primefields provide their own templates instead of invoking goff. For these workers, template code appears in a templates/ directory.
  • Some workers have code generated for them by other workers. Such code, if present, appears at the worker's root directory in generated-code.go.
  • Some workers might have complicated generation code. In order to keep generate.go simple, this extra generation code is typically split into other source files at the worker's root. (Example: computation of Frobenius constants in pairing/constants.go.)

…fp. TODO: generate all code for one curve before moving on to the next
…pairing, recover bls381 pairing as a sanity check
…o as to split Frobenius code from pairing.go like in bls381. This allows convenient diff checking for the new way to generate Frobenius constants
…enius constants automatically from the new template
…generate primefields for all curves in sequence; coooool
…ng for all 4 curves; TODO pairing for bw6-761 is incomplete, still need to port gpoint to the new architecture
@ggutoski
Copy link
Contributor Author

ggutoski commented Jun 3, 2020

By the way, this PR also contains some new code for BW6-761 pairing: Frobenius and final exponentiation.

TODO for BW6-761

  • mulAssign for lineEval to finish off the pairing
  • tests

@ggutoski ggutoski mentioned this pull request Jun 4, 2020
…ator---it's mostly curve-specific code anyway; restore go generate ./internal/... in config.yml; regenerate code
@ggutoski
Copy link
Contributor Author

We now have a working pairing for BW6-761. Ready to merge.

Several optimizations remain TODO. For example:

Clean-up TODO:

  • Work for clean up: MulByV, etc #7 has begun with BW6-761. The methods MulByVMinusThree, MulByVminusTwo, MulByVminusFive introduced for BW6-761 appear in pairing.go. Need to do the same for other curves and modify the template generator accordingly.
  • The template for pairing.go is a mess. Most of the code here is curve-specific. Most or all of this code should be removed from the template generator.

@ggutoski ggutoski merged commit dd8b416 into feature/bw6-761 Jun 15, 2020
@ggutoski ggutoski deleted the experimental-pairing-gen branch June 15, 2020 18:19
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.

None yet

2 participants