-
Notifications
You must be signed in to change notification settings - Fork 0
/
genesis.go
171 lines (150 loc) · 4.35 KB
/
genesis.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package types
import (
"fmt"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
proto "github.com/gogo/protobuf/proto"
)
// DefaultNextProposalID is the starting poiint for proposal IDs.
const DefaultNextProposalID uint64 = 1
// NewGenesisState returns a new genesis state object for the module.
func NewGenesisState(nextProposalID uint64, committees []Committee, proposals Proposals, votes []Vote) *GenesisState {
packedCommittees, err := PackCommittees(committees)
if err != nil {
panic(err)
}
return &GenesisState{
NextProposalID: nextProposalID,
Committees: packedCommittees,
Proposals: proposals,
Votes: votes,
}
}
// DefaultGenesisState returns the default genesis state for the module.
func DefaultGenesisState() *GenesisState {
return NewGenesisState(
DefaultNextProposalID,
Committees{},
Proposals{},
[]Vote{},
)
}
func (gs GenesisState) GetCommittees() Committees {
committees, err := UnpackCommittees(gs.Committees)
if err != nil {
panic(err)
}
return committees
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (data GenesisState) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error {
for _, any := range data.Committees {
var committee Committee
if err := unpacker.UnpackAny(any, &committee); err != nil {
return err
}
}
for _, p := range data.Proposals {
err := p.UnpackInterfaces(unpacker)
if err != nil {
return err
}
}
return nil
}
// Validate performs basic validation of genesis data.
func (gs GenesisState) Validate() error {
// validate committees
committeeMap := make(map[uint64]bool, len(gs.Committees))
committees, err := UnpackCommittees(gs.Committees)
if err != nil {
return err
}
for _, com := range committees {
// check there are no duplicate IDs
if _, ok := committeeMap[com.GetID()]; ok {
return fmt.Errorf("duplicate committee ID found in genesis state; id: %d", com.GetID())
}
committeeMap[com.GetID()] = true
// validate committee
if err := com.Validate(); err != nil {
return err
}
}
// validate proposals
proposalMap := make(map[uint64]bool, len(gs.Proposals))
for _, p := range gs.Proposals {
// check there are no duplicate IDs
if _, ok := proposalMap[p.ID]; ok {
return fmt.Errorf("duplicate proposal ID found in genesis state; id: %d", p.ID)
}
proposalMap[p.ID] = true
// validate next proposal ID
if p.ID >= gs.NextProposalID {
return fmt.Errorf("NextProposalID is not greater than all proposal IDs; id: %d", p.ID)
}
// check committee exists
if !committeeMap[p.CommitteeID] {
return fmt.Errorf("proposal refers to non existent committee; committee id: %d", p.CommitteeID)
}
// validate pubProposal
if err := p.ValidateBasic(); err != nil {
return fmt.Errorf("proposal %d invalid: %w", p.ID, err)
}
}
// validate votes
for _, v := range gs.Votes {
// validate committee
if err := v.Validate(); err != nil {
return err
}
// check proposal exists
if !proposalMap[v.ProposalID] {
return fmt.Errorf("vote refers to non existent proposal; vote: %+v", v)
}
}
return nil
}
// PackCommittees converts a committee slice to Any slice
func PackCommittees(committees []Committee) ([]*cdctypes.Any, error) {
committeesAny := make([]*cdctypes.Any, len(committees))
for i, committee := range committees {
any, err := PackCommittee(committee)
if err != nil {
return nil, err
}
committeesAny[i] = any
}
return committeesAny, nil
}
// PackCommittee converts a committee to Any
func PackCommittee(committee Committee) (*cdctypes.Any, error) {
msg, ok := committee.(proto.Message)
if !ok {
return nil, fmt.Errorf("cannot proto marshal %T", committee)
}
any, err := cdctypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return any, nil
}
// UnpackCommittees converts Any slice to Committee slice
func UnpackCommittees(committeesAny []*cdctypes.Any) (Committees, error) {
committees := make(Committees, len(committeesAny))
for i, any := range committeesAny {
committee, err := UnpackCommittee(any)
if err != nil {
return nil, err
}
committees[i] = committee
}
return committees, nil
}
// UnpackCommittee converts Any to Committee
func UnpackCommittee(committeeAny *cdctypes.Any) (Committee, error) {
committee, ok := committeeAny.GetCachedValue().(Committee)
if !ok {
return nil, fmt.Errorf("unexpected committee when unpacking")
}
return committee, nil
}