2 Data is designed to provide a standard interface and helper functions to
3 easily allow serialization and deserialization of your data structures
4 in both binary and json representations.
6 This is commonly needed for interpreting transactions or stored data in the
7 abci app, as well as accepting json input in the light-client proxy. If we
8 can standardize how we pass data around the app, we can also allow more
9 extensions, like data storage that can interpret the meaning of the []byte
10 passed in, and use that to index multiple fields for example.
12 Serialization of data is pretty automatic using standard json and go-wire
13 encoders. The main issue is deserialization, especially when using interfaces
14 where there are many possible concrete types.
16 go-wire handles this by registering the types and providing a custom
19 var _ = wire.RegisterInterface(
21 wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519},
22 wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1},
25 func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
26 err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey)
30 func (pubKey PubKeyEd25519) Bytes() []byte {
31 return wire.BinaryBytes(struct{ PubKey }{pubKey})
34 This prepends a type-byte to the binary representation upon serialization and
35 using that byte to switch between various representations on deserialization.
36 go-wire also supports something similar in json, but it leads to kind of ugly
37 mixed-types arrays, and requires using the go-wire json parser, which is
38 limited relative to the standard library encoding/json library.
40 In json, the typical idiom is to use a type string and message data:
43 "type": "this part tells you how to interpret the message",
44 "data": ...the actual message is here, in some kind of json...
47 I took inspiration from two blog posts, that demonstrate how to use this
48 to build (de)serialization in a go-wire like way.
50 * http://eagain.net/articles/go-dynamic-json/
51 * http://eagain.net/articles/go-json-kind/
53 This package unifies these two in a single Mapper.
55 You app needs to do three things to take full advantage of this:
57 1. For every interface you wish to serialize, define a holder struct with some helper methods, like FooerS wraps Fooer in common_test.go
58 2. In all structs that include this interface, include the wrapping struct instead. Functionally, this also fulfills the interface, so except for setting it or casting it to a sub-type it works the same.
59 3. Register the interface implementations as in the last init of common_test.go. If you are currently using go-wire, you should be doing this already
61 The benefits here is you can now run any of the following methods, both for
62 efficient storage in our go app, and a common format for rpc / humans.
66 // read/write binary a la tendermint/go-wire
68 err := wire.ReadBinaryBytes(
69 wire.BinaryBytes(orig), &bparsed)
71 // read/write json a la encoding/json
73 j, err := json.MarshalIndent(orig, "", "\t")
74 err = json.Unmarshal(j, &jparsed)
76 See https://github.com/tendermint/go-wire/data/blob/master/common_test.go to see
77 how to set up your code to use this.