rchain / rchip-proposals

Where RChain improvement proposals can be submitted
Apache License 2.0
8 stars 5 forks source link

Add rho:io:serialize fixed channel to Rholang #22

Open arthurgreef opened 4 years ago

arthurgreef commented 4 years ago

Motivation

Contracts that return json serialized terms are easier to parse in web apps. Currently web apps need to parse Rholang expressions to access data.

Motivating Examples

new ser(`rho:io:serialize`), out(`rho:io:stdout`), ack in {
    out!(("Not serialized", {"key":"data"})) |   // Stdout serialized the map
    ser!({"key":"data"}, *ack) |                 // Serialized ther map to a json string
    for(@res <- ack) {
        out!(("Serialized", res))                // String can be returned to web apps
    }
}

Design

Add a fixed channel to Rholang and expose built in term serializer.

SystemProcess
      .Definition[F]("rho:io:serialize", FixedChannels.SERIALIZE, 2, BodyRefs.SERIALIZE, {
        ctx: SystemProcess.Context[F] =>
          ctx.systemProcesses.serialize
      }),

Serialize is already part of the interpreter. It is just not exposed as a channel.

References

Prototype by is here tgrospic is here: https://github.com/tgrospic/rchain/blob/8458e467e95739538965782947fb8b51404ce4bb/rholang/src/main/scala/coop/rchain/rholang/interpreter/Runtime.scala#L215

jimscarver commented 4 years ago

Why not make serialize a function rather than a powerbox function? Why do we need to do a send and receive? @leithaus https://rchain.atlassian.net/wiki/spaces/CORE/pages/238158228/Node+Powerbox

dckc commented 4 years ago

I don't see mention of toByteArray . It does protobuf rather than json. In hindsight, toProtoBuf might have been a better name... Let's at least not make that mistake again, so toJSON please.

And like toByteArray, I see no reason for send/receive. A method should work.

tgrospic commented 4 years ago

My initial design was just a quick way to get JSON string from Rholang term. https://github.com/tgrospic/rchain/commit/dc4303bd38bd9db9243252bfd8d1cc09e026df1b#diff-24683beef03bd4a247ee96956b0125b9R125

I agree that can be converted to method on any Rholang term because this is the main argument.

The problem is what this method returns. It's calling PrettyPrinter#buildString to generate string representation of AST. Until we have detailed specification how each term should be serialized with all the caveats like different CR/LF on different systems, it will be very unstable to include this extension.

Attention should be also on relation between serialize and parse operations. It would be useful if this holds, similar how is in Haskell read and show. parse . serialize == identity

If serialize returns all Rholang terms as original Rholang code it will not be valid JSON or if only some expressions are converted. The use case can be very different.


Except to serialize subset of Rholang to JSON this method can be useful to display existing Rholang code in the Registry to help with library management https://github.com/rchain/rchip-proposals/issues/1.

We should analize if this method is really needed on chain or it will be mostly used to get the data from read-only node. In that case even if buildString is not written in stone, result will not be validated on chain. This means if serialize can be called only on read-only node we don't need that much of discipline and specificity. This also creates additional different behavior of the same Rholang code which put more burden to the user. Especially in this evolving phase of Rholang and without good reference documentation or errors with additional context with examples. Another aspect is difficulty of implementation of this dual behavior. Currently interpreter does not have any management of different environments.


These are two approaches how to include the feature but what are the alternatives? It is more relevant for HTTP than gRPC. HTTP already is doing similar role, it converts Rholang AST to JSON so improving that part can gives us even better translation. Certainly does not involve translation to string as intermediate structure (not counting HTTP layer). This is not really the same as serialize in Rholang but I assuming it's relevant for this use case.

Current implementation is done with circe library which serializes Scala case classes in not so intuitive way. I didn't find easy way to improve it without a lot of boiler plate code. I specified what is the challenge there if someone is willing to dig more into circe. :1st_place_medal: https://github.com/rchain/rchain/pull/2811/files#r355610199


@dckc protobuf is serialized to string so maybe toString makes some sense.

dckc commented 4 years ago

...

We should analize if this method is really needed on chain or it will be mostly used to get the data from read-only node.

Oh. Excellent point. Addressing this in the node API addresses the stated motivation: "easier to parse in web apps".

I was uneasy adding this in addition to toByteArray to on-chain rholang; I think this point is compelling.