-
Notifications
You must be signed in to change notification settings - Fork 113
/
genesis.go
162 lines (132 loc) · 4.43 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
package types
import (
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/cosmos/cosmos-sdk/codec"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/axelarnetwork/axelar-core/x/multisig/exported"
"github.com/axelarnetwork/utils/slices"
)
// NewGenesisState is the constructor for GenesisState
func NewGenesisState(params Params, keygenSessions []KeygenSession, signingSessions []SigningSession, keys []Key, keyEpochs []KeyEpoch) *GenesisState {
return &GenesisState{
Params: params,
KeygenSessions: keygenSessions,
SigningSessions: signingSessions,
Keys: keys,
KeyEpochs: keyEpochs,
}
}
// DefaultGenesisState returns a genesis state with default parameters
func DefaultGenesisState() *GenesisState {
return NewGenesisState(
DefaultParams(),
[]KeygenSession{},
[]SigningSession{},
[]Key{},
[]KeyEpoch{},
)
}
// Validate performs a validation check on the genesis parameters
func (m GenesisState) Validate() error {
if err := m.Params.Validate(); err != nil {
return getValidateError(err)
}
if err := validateKeys(m.KeygenSessions, m.Keys); err != nil {
return getValidateError(err)
}
keys := slices.ToMap(m.Keys, func(key Key) exported.KeyID { return key.ID })
if err := validateSigningSessions(keys, m.SigningSessions); err != nil {
return getValidateError(err)
}
if err := validateKeyEpochs(keys, m.KeyEpochs); err != nil {
return getValidateError(err)
}
return nil
}
func validateKeyEpochs(keys map[exported.KeyID]Key, keyEpochs []KeyEpoch) error {
keyIDSeen := make(map[string]bool, len(keyEpochs))
for _, keyEpochsOfChain := range slices.GroupBy(keyEpochs, func(keyEpoch KeyEpoch) string { return keyEpoch.GetChain().String() }) {
sort.SliceStable(keyEpochsOfChain, func(i, j int) bool { return keyEpochsOfChain[i].Epoch < keyEpochsOfChain[j].Epoch })
for i, keyEpoch := range keyEpochsOfChain {
if keyEpoch.Epoch != uint64(i+1) {
return fmt.Errorf("invalid epoch set for key epoch")
}
keyIDLowerCase := strings.ToLower(keyEpoch.GetKeyID().String())
if keyIDSeen[keyIDLowerCase] {
return fmt.Errorf("duplicate key ID seen in key epochs")
}
keyIDSeen[keyIDLowerCase] = true
key, ok := keys[keyEpoch.GetKeyID()]
if !ok {
return fmt.Errorf("key ID %s in key epoch does not exist", keyEpoch.GetKeyID())
}
switch key.State {
case exported.Assigned:
if i != len(keyEpochsOfChain)-1 {
return fmt.Errorf("invalid state for key %s", key.GetID())
}
case exported.Inactive:
return fmt.Errorf("invalid state for key %s", key.GetID())
}
if err := keyEpoch.ValidateBasic(); err != nil {
return err
}
}
}
return nil
}
func validateSigningSessions(keys map[exported.KeyID]Key, signingSessions []SigningSession) error {
sigIDSeen := make(map[uint64]bool, len(signingSessions))
for _, signingSession := range signingSessions {
if sigIDSeen[signingSession.GetID()] {
return fmt.Errorf("duplicate key ID seen")
}
sigIDSeen[signingSession.GetID()] = true
if _, ok := keys[signingSession.Key.ID]; !ok {
return fmt.Errorf("key ID %s in signature does not exist", signingSession.Key.ID)
}
if err := signingSession.ValidateBasic(); err != nil {
return err
}
}
return nil
}
func validateKeys(keygenSessions []KeygenSession, keys []Key) error {
keyIDSeen := make(map[string]bool, len(keygenSessions)+len(keys))
for _, keygenSession := range keygenSessions {
keyIDLowerCase := strings.ToLower(keygenSession.GetKeyID().String())
if keyIDSeen[keyIDLowerCase] {
return fmt.Errorf("duplicate key ID seen in keygen sessions")
}
keyIDSeen[keyIDLowerCase] = true
if err := keygenSession.ValidateBasic(); err != nil {
return err
}
}
for _, key := range keys {
keyIDLowerCase := strings.ToLower(key.GetID().String())
if keyIDSeen[keyIDLowerCase] {
return fmt.Errorf("duplicate key ID seen in keys")
}
keyIDSeen[keyIDLowerCase] = true
if err := key.ValidateBasic(); err != nil {
return err
}
}
return nil
}
func getValidateError(err error) error {
return sdkerrors.Wrapf(err, "genesis state for module %s is invalid", ModuleName)
}
// GetGenesisStateFromAppState returns the GenesisState given raw application
// genesis state.
func GetGenesisStateFromAppState(cdc codec.JSONCodec, appState map[string]json.RawMessage) GenesisState {
var genesisState GenesisState
if appState[ModuleName] != nil {
cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState)
}
return genesisState
}