You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The stdlib gob package can be used to encode Go objects over the wire. While trying to use it for encoding some core types, like channel.State or channel.Params, it didn't work out of the box.
I identified two problems:
If interfaces are to be sent over the wire, gob needs to be made aware of all possible implementations of those interfaces in advance using gob.Register. This is not the case for our implementations of wallet.Address, channel.Asset, channel.App, channel.Data or channel.Action, possibly others.
gob gets confused by interfaces that include gob.GobDecoder, gob.GobEncoder or encoding.BinaryMarshaler, encoding.BinaryUnmarshaler. If gob sees an object that implements those interfaces, it takes those implementations for en/decoding, which makes sense. However, it then doesn't transport the type information with the encoding, so the decoding side doesn't know which object to create. I found a Google groups discussion on the topic and a SO post.
I made the following observations that, if implemented, would hopefully make it work:
All concrete interface implementations in backends need to be registered using gob.Register, e.g. adding
funcinit() {
gob.Register((*Address)(nil))
}
to packages backend/{sim,ethereum}/wallet. Same for Assets, Apps etc. Make sure to use the correct type (pointer or no pointer) depending on what actually is used as the interface implementation (e.g. noApp is used as a non-pointer type).
2. All interfaces used in structs that are to be encoded with gob need to remove the embeddings of gob.GobDecoder, gob.GobEncoder or encoding.BinaryMarshaler, encoding.BinaryUnmarshaler. Of course, the concrete implementations can still implement those interfaces, but it is important that the struct field interface types don't reference those, or gob gets confused and uses the methods before encoding the type information. One solution could be to have two interfaces, like
and then require backends to implement Asset but use AssetGOB as the field type of assets in Allocation etc. The constructors like NewAllocation would still require Asset to make sure full Asset implementations are used but would then store the assets as AssetGOBs so that it can be used with gob encoding.
This Go Playground example shows what happens if gob.GobDecoder, gob.GobEncoder is part of an interface (rename Duck to DuckS in the two lines mentioned in main to see the problem).
The text was updated successfully, but these errors were encountered:
The stdlib
gob
package can be used to encode Go objects over the wire. While trying to use it for encoding some core types, likechannel.State
orchannel.Params
, it didn't work out of the box.I identified two problems:
gob
needs to be made aware of all possible implementations of those interfaces in advance usinggob.Register
. This is not the case for our implementations ofwallet.Address
,channel.Asset
,channel.App
,channel.Data
orchannel.Action
, possibly others.gob
gets confused by interfaces that includegob.GobDecoder, gob.GobEncoder
orencoding.BinaryMarshaler, encoding.BinaryUnmarshaler
. Ifgob
sees an object that implements those interfaces, it takes those implementations for en/decoding, which makes sense. However, it then doesn't transport the type information with the encoding, so the decoding side doesn't know which object to create. I found a Google groups discussion on the topic and a SO post.I made the following observations that, if implemented, would hopefully make it work:
gob.Register
, e.g. addingto packages
backend/{sim,ethereum}/wallet
. Same forAsset
s,App
s etc. Make sure to use the correct type (pointer or no pointer) depending on what actually is used as the interface implementation (e.g.noApp
is used as a non-pointer type).2. All interfaces used in structs that are to be encoded with
gob
need to remove the embeddings ofgob.GobDecoder, gob.GobEncoder
orencoding.BinaryMarshaler, encoding.BinaryUnmarshaler
. Of course, the concrete implementations can still implement those interfaces, but it is important that the struct field interface types don't reference those, orgob
gets confused and uses the methods before encoding the type information. One solution could be to have two interfaces, likeand then require backends to implement
Asset
but useAssetGOB
as the field type of assets inAllocation
etc. The constructors likeNewAllocation
would still requireAsset
to make sure fullAsset
implementations are used but would then store the assets asAssetGOB
s so that it can be used withgob
encoding.This Go Playground example shows what happens if
gob.GobDecoder, gob.GobEncoder
is part of an interface (renameDuck
toDuckS
in the two lines mentioned inmain
to see the problem).The text was updated successfully, but these errors were encountered: