/
unmarshal.go
133 lines (123 loc) · 3.45 KB
/
unmarshal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package light_block
import (
"io"
"io/ioutil"
"github.com/vulcanize/go-codec-dagcosmos/commit"
"github.com/ipld/go-ipld-prime"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/types"
"github.com/vulcanize/go-codec-dagcosmos/header"
"github.com/vulcanize/go-codec-dagcosmos/shared"
)
// Decode provides an IPLD codec decode interface for Cosmos LightBlock IPLDs.
// This function is registered via the go-ipld-prime link loader for multicodec
// code XXX when this package is invoked via init.
func Decode(na ipld.NodeAssembler, in io.Reader) error {
var src []byte
if buf, ok := in.(interface{ Bytes() []byte }); ok {
src = buf.Bytes()
} else {
var err error
src, err = ioutil.ReadAll(in)
if err != nil {
return err
}
}
return DecodeBytes(na, src)
}
// DecodeBytes is like Decode, but it uses an input buffer directly.
// Decode will grab or read all the bytes from an io.Reader anyway, so this can
// save having to copy the bytes or create a bytes.Buffer.
func DecodeBytes(na ipld.NodeAssembler, src []byte) error {
tmlb := new(tmproto.LightBlock)
if err := tmlb.Unmarshal(src); err != nil {
return err
}
lb, err := types.LightBlockFromProto(tmlb)
if err != nil {
return err
}
return DecodeLightBlock(na, *lb)
}
// DecodeLightBlock is like Decode, but it uses an input tendermint LightBlock type
func DecodeLightBlock(na ipld.NodeAssembler, lb types.LightBlock) error {
ma, err := na.BeginMap(2)
if err != nil {
return err
}
for _, upFunc := range requiredUnpackFuncs {
if err := upFunc(ma, lb); err != nil {
return err
}
}
return ma.Finish()
}
var requiredUnpackFuncs = []func(ipld.MapAssembler, types.LightBlock) error{
unpackSignedHeader,
unpackValidatorSet,
}
func unpackSignedHeader(ma ipld.MapAssembler, lb types.LightBlock) error {
if err := ma.AssembleKey().AssignString("SignedHeader"); err != nil {
return err
}
shMA, err := ma.AssembleValue().BeginMap(2)
if err != nil {
return err
}
if err := shMA.AssembleKey().AssignString("Header"); err != nil {
return err
}
if err := header.DecodeHeader(shMA.AssembleValue(), *lb.Header); err != nil {
return err
}
if err := shMA.AssembleKey().AssignString("Commit"); err != nil {
return err
}
commitMA, err := shMA.AssembleValue().BeginMap(4)
if err != nil {
return err
}
if err := commit.UnpackCommit(commitMA, *lb.Commit); err != nil {
return err
}
return shMA.Finish()
}
func unpackValidatorSet(ma ipld.MapAssembler, lb types.LightBlock) error {
if err := ma.AssembleKey().AssignString("ValidatorSet"); err != nil {
return err
}
valSetMA, err := ma.AssembleValue().BeginMap(2)
if err != nil {
return err
}
if err := valSetMA.AssembleKey().AssignString("Validators"); err != nil {
return err
}
valsLA, err := valSetMA.AssembleValue().BeginList(int64(len(lb.ValidatorSet.Validators)))
if err != nil {
return err
}
for _, validator := range lb.ValidatorSet.Validators {
valMA, err := valsLA.AssembleValue().BeginMap(4)
if err != nil {
return err
}
if err := shared.UnpackValidator(valMA, *validator); err != nil {
return err
}
}
if err := valsLA.Finish(); err != nil {
return err
}
if err := valSetMA.AssembleKey().AssignString("Proposer"); err != nil {
return err
}
proposerMA, err := valSetMA.AssembleValue().BeginMap(4)
if err != nil {
return err
}
if err := shared.UnpackValidator(proposerMA, *lb.ValidatorSet.Proposer); err != nil {
return err
}
return valSetMA.Finish()
}