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

Add an option to emit deterministic code exclusively #465

Open
vgrichina opened this issue Feb 6, 2019 · 11 comments
Open

Add an option to emit deterministic code exclusively #465

vgrichina opened this issue Feb 6, 2019 · 11 comments

Comments

@vgrichina
Copy link

Smart contracts for blockchain need to be fully deterministic.
As I understand it's not generally possible with floats (because of minor CPU differences).

We need to have an option to compile without floats. I think some parts of std use floats unexpectedly as replacement for number which may pose some problems with this.

@dcodeIO
Copy link
Member

dcodeIO commented Feb 6, 2019

Would it also be sufficient to disable them, e.g. emit an error whenever a float would slip into the binary?

@MaxGraey
Copy link
Member

MaxGraey commented Feb 6, 2019

May be better validate this on wasm vm (backend) and via custom ts-lint rules on frontend?

@dcodeIO
Copy link
Member

dcodeIO commented Feb 6, 2019

A more general mechanism I'd think of in this context could be a --deterministic flag or similar, that would then deem any non-deterministic moving parts as unsafe (floats, concurrent gc, whatnot), and require something like an explicit unsafe(...) context to force it to compile (if one knows what he's doing).

@MaxGraey
Copy link
Member

MaxGraey commented Feb 6, 2019

btw life's vm which specially designed for blockchain supported float points (it seems just avoiding non-deterministics with qNaN and sNaN).

https://github.com/perlin-network/life/blob/d05763d110500d0a2bf15724c6aee6b225437a87/exec/vm.go#L1285

But currently their vm works as interpreter without jit

EDIT
But I remember they are also disable floats in first time.

@vgrichina
Copy link
Author

vgrichina commented Feb 7, 2019

Would it also be sufficient to disable them, e.g. emit an error whenever a float would slip into the binary?

yes, but std shouldn't break down because of this. Like of course stuff explicitly working with floats shouldn't work, but I think some stuff still has implicit dependencies because of JS number.

May be better validate this on wasm vm (backend) and via custom ts-lint rules on frontend?

This will be validated again when smart contracts are deployed. But we want some friendly errors with source code lines, etc. And std which won't use f64 for non-float stuff. Like right now Math.max forces floats usage, etc.

A more general mechanism I'd think of in this context could be a --deterministic flag

I like this. Generally it is even possible (long-term, we don't really need this) to implement floats in deterministic way, they just gonna be really slow.

@MaxGraey
Copy link
Member

MaxGraey commented Feb 7, 2019

@vgrichina You don't need slow emulation float points (soft-floats) because WebAssembly fully deterministic even for operations like sqrt and subnormals on 64-bit ARM. Only one thing which you should care is NaNs. So you just need verify NaN status after every float operations which just one extra check and choose vm which fully cover wasm spec tests

@dcodeIO
Copy link
Member

dcodeIO commented Feb 7, 2019

So, it looks like implementing a --deterministic mode right into the compiler might be a better solution than just disabling floats per-se. Going to update the title accordingly.

@dcodeIO dcodeIO changed the title An option to compile without float types Add an option to emit deterministic code exclusively Feb 7, 2019
@vgrichina
Copy link
Author

@dcodeIO I think there is still a cause for cleaning up std to not use floats for stuff that should be generic for numbers, e.g. Math.max. But makes sense to spin-off into separate issue.

@MaxGraey
Copy link
Member

MaxGraey commented Feb 7, 2019

@vgrichina Whole Math namespace should be disabled in --deterministic mode because it fully relate to float-point functions and operations (even Math.imul and Math.clz32). Instead AS have built-in generics min/max and etc which you can check here: https://github.com/AssemblyScript/assemblyscript/wiki/Built-ins#math

Just need exclude isNaN, isFinite, copysign, sqrt, trunc, nearest/floor/ceil and reinterpret in this mode

@dcodeIO
Copy link
Member

dcodeIO commented Feb 8, 2019

For context: So far, pretty much everything within Math is f64 because we approached this from a compatibility (to JS) standpoint. One reason to do it this way is that the entire Math namespace can also be replaced with imported Math from a browser for example, which wouldn't have generic functionality.

As noted by Max, there are other builtins that also work with integers, like max<T>(a, b) that, even though there are no min/max instructions in WASM, emits a select when integers are passed to it for convenience.

One solution here could be a DeterministicMath class or similar, that could be used instead of normal Math in a scenario like yours through --use Math=DeterministicMath. It could exclude specific functionality, implement integer-only or generic methods or do special checking for NaNs. Might even be the default in --deterministic.

@vgrichina
Copy link
Author

One solution here could be a DeterministicMath class or similar, that could be used instead of normal Math in a scenario like yours through --use Math=DeterministicMath. It could exclude specific functionality, implement integer-only or generic methods or do special checking for NaNs. Might even be the default in --deterministic.

I like this proposal!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants