-
-
Notifications
You must be signed in to change notification settings - Fork 39
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
BigInt syntax errors in unsupported environments #12
Comments
EDIT: I actually have this issue as it stands in the current version of my libs, i.e. had this (it is not used anywhere, only declared in a file that has a function exported) - const SQRT_MAX_SAFE_INTEGER = 94906265n; Took a similar "hack" approach now as laid out above (to not spend all day on issues) to get around it with a |
Made a PR here since I had a small gap and always prefer seeing things in code - #13 However, feel free to close this and that after some thought it is absolutely horrid in your eyes, it is just an approach. |
If there are no bigints, we should absolutely NOT fall back to something else, and instead an error should be thrown. It's like falling back to "math random" when crypto.secureRandom is not available. Very bad idea. |
Agreed. So in this case, there is detection - return typeof BigInt !== 'undefined'
? somethingWithBi(...)
: somethingWithNoBi(...) The issue is the build steps - it pulls in all code (even unused libs) and then fails on things like So there are def. 2 parts -
|
Can I ask, why? WASM:
If the old env is able to import the code, but then fails immediately, what's the point here? I think the environments must update to be compliant with modern ECMAScript. Leaving bigint code as-is would increase the pressure on build tools to be compliant. E.g. if we merge the pull request, less people would know about the problem, and less people would report to react-native. Anyway i'll leave the PR open for now until we get more environment examples. If enough people report this, we'll prob go ahead. Note that it's not just noble-hashes that needs to be adjusted, it's also all other noble libraries. |
Another question. How would your env handle an error that would be thrown if the bigints do not exist, during the runtime Can the error be catched? |
Also, it seems like the most recent react-native supports bigints. The problem only resides in devices with ios 13.7 or earlier. (current is v15) |
100% - however, I'm already this week flooded with support and all I did was adding unused bi utils :) The plan is to swap to noble in the next major release (which I want to do soon), however I cannot force everybody to upgrade their environments, but a lot of times I do have to force them to upgrade my libs and if the two don't quite work as expected, great unhappiness. (In the case of RN, according to the Ledger Live developers, it may be solved by an upgrade from Expo to Hermes, but it is not a small undertaking. Current version of my libs, even before So I will point you to actual (in master branch) code using https://github.com/polkadot-js/common/blob/master/packages/util-crypto/src/blake2/asU8a.ts#L33-L35 The Rust libs used for WASM is part of the audit for the Polkadot runtime, i.e. use the same versions as there. So yes, I agree, it is not readable, e.g. https://github.com/polkadot-js/wasm/tree/master/packages/wasm-crypto/src/rs and it brings a host of other issues with it (i.e. for React Native it also needs asm.js since it doesn't do Webassembly... but at least in this case it now provides a fallback for that env) So, in my case, I guess for the time being I'll revert Sadly I deal with a lot of different environments using the libs and, well, I would love to tell them to just not use it, but the ecosystem has no other options apart from what is provided by my libs - so that needs to cater for a wide spectrum. I am trying my best to drive forward bit by bit (and not get held back). As for other libs, I am aware of it, i.e. the |
So, if we merge the BigInt changes to secp and hashes, would that help your users with old React Natives? Does RN support BigInts, just not syntax? |
Yes, it would allow me to swap over completely. On some environments, e.g. iOS, will have 100% support - on some older RN the fallbacks would be used. However, it does mean it can be available for 99% of end-users with no issues (i.e. have JS hashing available, the remainder is on fallback) and available for 100% of all library users with no issues in their tooling. In the end it needs to make 100% sense here, if not it should not go in. Sometimes I wish it was 2025 already and 2020-era new is everywhere... :) |
The question is still in the error thrown on import. Would you be able to handle it? |
On use of a non-compliant function, indeed. An example of this is the So on my side (others may do it differently), each hashing function has a check for (secp, when I get to it, will be different, with no BigInt it will just fail outright without even trying to call into On import itself, I don't have lazy imports, so if I do - import { blake2b } from '@noble/hashes/lib/blake2b'; and that fails, there is an issue. However when calling into Does that make sense? |
I'm thinking about throwing an error on import. What users of yours would be affected by it? |
Really not 100%. Will need to see what it looks like code-wise at the end to determine impact. It is probably mostly my RN users. It is more tricky to determine capability paths (for me downstream) at import. Obviously at runtime things like this (random example) would work without issues - class BLAKE2b extends blake2.BLAKE2<BLAKE2b> {
// Same as SHA-512, but LE
// ... snipped ...
constructor(opts: blake2.BlakeOpts = {}) {
if (typeof BigInt ==='undefined') throw new Error('BigInt is not available'); But it does have a slight runtime impact. At file level it would be trickier (for me), but I'm guessing it is the 100% clear solution here for this. |
yeah, I don't want runtime impacts for stuff that's used by 1% of users. I don't see big disadvantages in changing 1n to BigInt(1) tho. |
Just as a side note, this is something i have also ran into trying to support react-native usage of my library |
Thanks @jacogr, i've added this, but without _n util. You'll need to replace |
Thank you. I think that is a sane approach. |
Edit to the above: I have something similar for secp256k1 (in this case also BigInt(…) wrappers), will contribute… once again if somebody doesn’t get there before me… |
... you are not going to like this one, bear with me :)
Ok, I started pulling this in. Basically in my case I still need to support some ancient environments as well, which is not that much of an issue, basically on my hashing wrappers I do the following -
So effectively there is some fallback in there. (The above is typed from memory as illustration, but shows the point. Normally when wasm is initialized, it actually is the preferred route in my case. The same applies to eg fallback to blake2-js when BigInt is not available)
Anyway, all good. Now however the issue is the following - on some older environments, such as for instance React Native, it even throws up when trying to parse the modules, e.g. this is problematic (although not used at runtime) https://github.com/paulmillr/noble-hashes/blob/main/src/_u64.ts#L1
I did a quick search for the
32n
e.g./\dn/
and there are actually not that many. So for instance, we could get around it with the following ...The above is problematic, obviously since it will give undefined results in non-BigInt environments. In BigInt environments there is no extra overhead, well, maybe slightly at library load. However for non-BigInt-envs inside functions it does use
BigInt
which would throw up at runtime.At this point the TL;DR is -
So my options are -
None of the options are fun atm :) Other suggestions welcome.
The text was updated successfully, but these errors were encountered: