Convex-Dev / convex

Convex Main Repository - Decentralised platform for the Internet of Value
https://convex.world
Other
95 stars 30 forks source link

Recompiling decompiled cells #250

Open helins opened 3 years ago

helins commented 3 years ago

Given that the CVX runner allow users to read strings, I was trying to decompile some cells. It can be a unique and powerful feature, for instance decompiling a function to a list and inspect it programmatically.

In this case, decompilation is as easy as print -> read.

The only problem is that recompiling is not reliable since local bindings are converted to %X.

Hence:

(def f (fn [a] (inc a))

(str f)  ;;  "(fn [a] (inc %0))"

(def f-data
       '(fn [a] (inc %0)))  ;;  Emulating reading

((eval f-data) 42)

;; UNDECLARED, since `%0` is interpreted back as a symbol and it is effectively not declared.

Solution: expand (or compile) %X symbols as access to local bindings ; a low-level feature common users won't have to worry about but which could allow powerful ideas.

mikera commented 3 years ago

Other option might be to print the params as [%0 %1 ...].

This would enable us to erase parameter names, which is good for performance and similar to what unison-lang does

helins commented 3 years ago

Indeed, it would be cleaner. However, something like (fn [a] (inc %0)) allows anyone to restore names I think? If it is the case then it's useful for inspection (eg. the sandbox could walk a function "rehydrate" the placeholders).

Replacing original targets with positional notation is cleaner but looses names forever. Interpreting %X as positional access looks weirder as such but presumably allows consumers to restore names.

mikera commented 3 years ago

I think actual param names are best left to descriptive documentation? The names in code aren't so useful on their own, with a lot of things like [& args] used which require some interpretation.

helins commented 3 years ago

But then there are local bindings (let, loop), it's not only about params.

My only concern is having easily readable code, I'd like Convex to be as easy and accessible as possible. Loosing names definitely would make that a lot harder. What do you think?

An alternative is to have opaque code on chain (like ETH does) and then a service which ensures that a given source indeed compiles to what is on chain. However it adds complexity and it's not very Lispy.

mikera commented 3 years ago

Well, code should be readable but once compiled functions are more like opaque objects (there's currently no way to destructure them in CVM code, for example). A semi-readable print would be nice for dev / debugging purposes but it's not really a priority. My preference is probably to keep all stuff intended for human consumption at the metadata level in a consistent way

helins commented 3 years ago

What I always thought was an important property of Convex is that you can always easily query the environment of an actor and see exactly what it does. It's a powerful feature for a "trustless" system, the fact you don't need anyone nor any additional service to know exactly what to expect.

From where I stand it's not just about dev but very much about that kind of things.

I don't think there is any good alternative, especially given that queries can be possibly free (depending on peer). If you wanted to compile source (provided you have access to it) and check for yourself, you would have to to it on-chain.