-
Notifications
You must be signed in to change notification settings - Fork 110
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
Remove top-level await #1583
Remove top-level await #1583
Conversation
Thanks for putting this together. I'm a little concerned that we haven't totally confirmed this as the root cause for next. I think there's also a bug in package.json and exports. I wonder if we can add a test?
For client side (web) we'd have to test rendering an app. Is that what playwright is for? |
Removing top-level await is also very helpful for non-web environments. For example, it is a blocker for using Netlify functions or some typescript configurations. |
I agree that it might seem like the wrong order, but
I'll add the package.json tweak in this PR though! |
No I think it's the right order. This is very important. My main point is that we should add a test for client and server side components in next. Full steam ahead on removing top level await! Thanks for getting that going. |
But if you wanna follow that up in a later PR, that also makes sense. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
most of the PR is fixing tests -- highlighted some of the actual changes
@@ -875,28 +875,11 @@ class AccountUpdate implements Types.AccountUpdate { | |||
} | |||
|
|||
hash(): Field { | |||
// these two ways of hashing are (and have to be) consistent / produce the same hash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
finally had to remove this, because it would have meant account update hashing depends on the bindings
@@ -45,10 +45,11 @@ export { LocalBlockchain }; | |||
/** | |||
* A mock Mina blockchain running locally and useful for testing. | |||
*/ | |||
function LocalBlockchain({ | |||
async function LocalBlockchain({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LocalBlockchain
-> async
await initializeBindings(); | ||
let [, data, hash] = Pickles.dummyVerificationKey(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awaiting bindings in deploy()
, to use Pickles
src/lib/proof-system/circuit.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awaiting bindings in Circuit
APIs
@@ -110,18 +110,21 @@ class Proof<Input, Output> { | |||
proof: Pickles.proofToBase64([this.maxProofsVerified, this.proof]), | |||
}; | |||
} | |||
static fromJSON<S extends Subclass<typeof Proof>>( | |||
static async fromJSON<S extends Subclass<typeof Proof>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proof.fromJSON()
becomes async because it needs Pickles
and there's the chance people call this without calling compile()
first
@@ -198,14 +198,13 @@ class Bool { | |||
* This can only be called on non-witness values. | |||
*/ | |||
toBoolean(): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I restructured this so that toBoolean()
doesn't need Snarky
to be defined when the input is constant.
When the input is a variable, it's fine to rely on Snarky
because one of the circuit running methods must have been called first, and they are all guarded by initializeBindings()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're awaiting bindings in every method that runs provable code, so that this code is able to use the Snarky
import
@@ -33,6 +33,7 @@ type ProvableHashable<T> = Provable<T> & Hashable<T>; | |||
class Sponge { | |||
#sponge: unknown; | |||
|
|||
// TODO: implement constant version in TS. currently, you need to call `initializeBindings()` before successfully calling this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left this as TODO. Poseidon.Sponge()
cannot be used before initializing bindings first, which could lead to users experiencing errors. I think the function is rarely used though, and there's an easy workaround: call initializeBindings()
. The eventual solution is to implement Sponge()
in TS (should be similar to Poseidon.hash()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easy/worthwhile to add an error message to call initializeBindings()
until Sponge()
is implemented in TS? It could be done in the future if so.
src/snarky.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is how the Node.js bindings work now
src/snarky.web.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is how the web bindings work now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm excited for theses changes! Nice work! I had some minor comments and questions.
CHANGELOG.md
Outdated
@@ -28,19 +28,25 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm | |||
- Add assertion to the foreign EC addition gadget that prevents degenerate cases https://github.com/o1-labs/o1js/pull/1545 | |||
- Fixes soundness of ECDSA; slightly increases its constraints from ~28k to 29k | |||
- Breaks circuits that used EC addition, like ECDSA | |||
- `Mina.LocalBlockchain()` is made async https://github.com/o1-labs/o1js/pull/1583 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will require updates in the docs as well as the CLI.
@@ -33,6 +33,7 @@ type ProvableHashable<T> = Provable<T> & Hashable<T>; | |||
class Sponge { | |||
#sponge: unknown; | |||
|
|||
// TODO: implement constant version in TS. currently, you need to call `initializeBindings()` before successfully calling this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easy/worthwhile to add an error message to call initializeBindings()
until Sponge()
is implemented in TS? It could be done in the future if so.
So glad these changes were merged. Is there a timeline for release to NPM? |
@sam-goodwin There is a plan to release early next week. We will let you know if things change. |
PrivateKey
on server in a NextJS 14 app #1575Mina.LocalBlockchain()
becomes asyncbindings: o1-labs/o1js-bindings#268
Details
Instead of awaiting bindings imports at the top-level, we hide them behind a new async function
initializeBindings()
.initializeBindings()
does not have to be called by users of o1js, because this PR takes care to call it first wherever bindings are needed.Almost all user-facing APIs which need to call
initializeBindings()
were already async -- making the remaining two async constitutes the two breaking changes of this PR:LocalBlockchain()
Proof.fromJSON()
We also export
initializeBindings()
for explicit control, which can be useful to front-load the bindings import in web apps.Loading time improvements
Because loading of the bindings is now deferred until it's needed, this comes with a great improvement for initial loading time of o1js. It will enable us to remove hacks to load o1js in a
useEffect()
or similar.logs in the browser console: