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

Foreign field operations #985

Merged
merged 75 commits into from
Dec 4, 2023
Merged

Foreign field operations #985

merged 75 commits into from
Dec 4, 2023

Conversation

mitschabaude
Copy link
Collaborator

@mitschabaude mitschabaude commented Jun 13, 2023

mina branch: feature/foreign-field-develop (currently no changes but depends on an open PR)
bindings: o1-labs/o1js-bindings#41

closes #961
closes #963

This PR adds a ForeignField class, which is created by the createForeignField class factory (taking the field modulus as parameter).

ForeignField aims for a DX similar to what developers are used to from Field, with a subset of methods that should be powerful enough for most use cases. So far, all methods are "safe" and fully constrain their outputs, which allows to use the class with confidence and no inside knowledge. An Unsafe API which allows advanced developers to save some constraints will be added in a separate PR.

EDIT: More info about recent changes in #985 (comment)

@mitschabaude
Copy link
Collaborator Author

mitschabaude commented Nov 30, 2023

This PR is officially revived! For the reviewer's convenience, here is the diff from the last review: d462e7c...4330a98

I made a bunch of changes to the original ForeignField class, the most impactful of which are:

  • the bulk of the class was moved outside the class factory function createForeignField(). The reason for that is that TS is not good at all about understanding the types of dynamically created classes (most methods end up having any inputs in the compiled d.ts file, even as they are fully typed in the source code). By moving the class outside we can use the precise types specified by it. The base class is of course not functional (it doesn't know its field modulus yet). So the pattern I use is to "inject" the dynamic parts into static properties that are possibly undefined, and then lift those to always defined properties by wrapping them with getters that throw an error.
  • second big change: instead of just having one class, I introduce three different variants of every foreign field class: Unreduced, AlmostReduced and Canonical. that way, I can have fine-grained control over which method expects which kind of range check on its inputs, and what range check is proved about its return value. This fine-grained control translates into not always having to add all constraints by default, so enabling fully efficient circuits without assuming too much prior knowledge (since the types already encode that knowledge). To understand how the classes work in detail, I recommend to read the doccomment on createForeignField(), and also to read through the new example: src/examples/crypto/foreign-field.ts

Copy link
Member

@Trivo25 Trivo25 left a comment

Choose a reason for hiding this comment

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

nice!

* ```
*
* Since asserting equality can also serve as a range check,
* this method returns `x` with the appropriate type:
Copy link
Member

Choose a reason for hiding this comment

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

I like the pattern of utilizing types to better reflect the "state" of a value!

src/lib/foreign-field.ts Outdated Show resolved Hide resolved
@mitschabaude mitschabaude merged commit d901dea into main Dec 4, 2023
13 checks passed
@mitschabaude mitschabaude deleted the feature/foreign-field branch December 4, 2023 16:02
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.

Expose FFMul Expose FFAdd
7 participants