-
Notifications
You must be signed in to change notification settings - Fork 18
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
☂️ Create abstractions to make the wire serialization protocol exchangable. #233
Comments
While working on this change,
Then I noticed, these interfaces were used in three contexts:
In the third case, the encoding/decoding will be implemented by the app backend and not the wire backend ?
// Current definition
type Action = perunio.Encoder
// Proposed
type Action interface {
Encode(io.Writer) error
} @sebastianst @matthiasgeihs What do you think ? |
The interfaces are still public, why do the current definitions of |
Because, the documentation of Data says it will be decoded by the App Backend and that of Action says it will be decoded by the action app backend. Which means, the encoding/decoding implementations for these packages are not defined by the wire protocol, but by the app backend ? However, as I see it from the high level perspective: there are two levels of encoding/decoding happening here. First: Encoding the data into an app-agnostic format (this should be done by the app backend), Second: Serializing the data for transferring it over the wire. Do you think we should use two different abstractions to address each of these aspects ? |
Yes I think we have to regard this as two different levels of en/decoding. It is app specific how to en/decode the data for itself, and the resulting/source |
Yes, in that case should we re-define the interface like shown below ?
Where the BinaryMarshaler and BinaryUnMarshaler interfaces are for converting the app specific data to and from binary format (byte array). Then, the wire serialization backend can deal with encoding/decoding the byte arrays without being concerned about the type of app/action/data. |
I have added a demo of how this will look like in the draft PR #242, commit 5ce5487.
|
OK, let me see if I understand correctly: The problem you are having is that for some types, we use their Encode function for different purposes that should potentially have different implementations. P1: Encoding onto the writer. Correct? Now you are saying you wanted to move the Encoder definition from the channel package to the wire package. And then you identified some problems. My question: Is it really a suitable approach to move the Encode definition? Maybe we need to step back and carefully think again how we want to achieve the goal of making the wire serialization work for new clients? Maybe in the end the easier approach is to document our encoding properly and then just implement it across all clients? Anyhow, it seems like a complex topic which we need to dedicate some more time to to get it right. We can do that in one of our upcoming calls. I had a brief look at your draft PR: having encoding.BinaryMarshaler, encoding.BinaryUnmarshaler in addition to Encode on each of the respective interfaces unfortunately doesn't look very clean to me. |
Yes, your understanding of the primary issue is correct. It is that for some types (
|
To your question on both It is just a draft to show, how the two concerns stated above can be implemented and which standard interfaces of golang (binary.Marshaler, binary.Unmarshaler) we can use. In the end, on some types (where encode function does two things stated above), |
I skimmed through your comments and the commit in the PR. Form what I understand, I think it does make sense to make this distinction between 1. (blockchain-dependent data serialization) and 2. (wire serialization). If I saw correctly, using |
@sebastianst Regarding the |
Points from discussion with @matthiasgeihs Currently, the After this refactor, it should be easier to create abstractions for the wire serialization. Hence, we could take up this task after the refactor. |
Update after meeting on Jan 11
Introduce wire.Encoder
type Encoder interface {
Encode(io.Writer, *Envelope) error
Decode(io.Reader) (*Envelope, error)
} Also add method
The following is to be considered as well:
@manoranjith Please check my additions and modify your issue description as necessary. |
@matthiasgeihs I have updated the issue description. Hope, I have covered all the points. Feel free to make suggestions/updates, if you find that I have missed anything. |
all tasks done |
Location
[wire], [pkg/io], [wire/net]
Motivation
Currently, wire messages in go-perun are encoded/decoded using a home-baked. When developing alternate implementations of the perun channel client, in a different programming language, the encoders and decoders have to be re-implemented in that language.
If we are able to exchange the custom format for standard ones like "protocol buffers", the messages can be defined once and the encoders/decoders can be generated for different programming languages. This will eliminate the overhead of implementing and maintaining the encoders/decoders in multiple languages.
However, this it is currently not possible to exchange custom format for a different one, as the necessary abstractions are missing. The scope of this task is to introduce the necessary abstractions.
Details
Abstractions necessary for making the wire serialization format exchangeable has been discussed and accepted in proposal#5.
This can be implemented in 6 steps, each involving one PR. This an umbrella issue to track the complete task.
Step 1
pkg/io
package towire/perun
. Move pkg/io to wire/perunio #285pkg/io/test
, which defines generic tests for encoders/decoders is moved towire/test
package. Merge perunio/test into wire/test #287Step 2 Add env serializer interface #297
EnvelopeSerializer
interface.EnvelopeSerializer
and an exported functionSetEnvelopeSerializer
, for setting it. The function should panic, if invoked more than once.EnvelopeSerializer
for perunio serialization format. The implementation should be placed in new package :wire/perunio/serializer
. Because, packagewire/perunio
cannot import packagewire
.init
function in packagewire/perunio/serializer
, which sets thewire.enveloperSerializer
to perunio envelope serializer.Remark: It would be nicer to have the
EnvelopeSerializer
implementation directly in packagewire/perunio
. However, this might require some refactoring (as described in step 7) and hence could be done later.Step 3 Add env serializer interface #297
wire.(Encode/Decode)
methods with functionsEncodeEnvelope
andDecodeEvelope
.Recv
andSend
onioconn
in thewire/net
package to use the newly defined functions instead ofwire.(Encode/Decode)
methods.Step 4 Use UnmarshalBinary and MarshalBinary for converting to/from Binary form #298
(Un)MarshalBinary
function instead ofperunio.(En|De)code
in places where data is to be converted to/from binary representation, but need not be written to the wire. In particular, see 75150e1 and 1dc0797.Step 5 (Can be done later)
wallet.Sig
. Described and tracked in Add an abstract type for wallet.Sig #292.Step 6 (Can be done later)
wire
package to thewire/perun
package.wire
package, decode envelopes instead of messages.Step 7 (Can be done later)
From the
client
package,wire
package andwire/perun
package.wire/perunio/serializer
package intowire/perunio
. Because, now it would be possible forwire/perunio
package to importwire
package.Notes:
Regarding persistence, we can continue to use the perunio protocol as that is used for wire serialization. This should continue to work without any additional changes unless we implement step 7. When we implement step 7, we could rethink how we should handle it.
Make
ProposalID
independent of perunio Mechanism for proposal ID generation #301Export all relevant all message types 💥 Off-chain messages: Naming conventions and type export for wire serialization #302
The text was updated successfully, but these errors were encountered: