-
Notifications
You must be signed in to change notification settings - Fork 11
/
change.go
167 lines (144 loc) · 4.58 KB
/
change.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
package types
import (
"encoding/json"
"fmt"
"strings"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// DefaultStartingChangeID is 1
const DefaultStartingChangeID uint64 = 1
// Change defines a struct used by the sync module to allow for voting
// on network changes.
type Change struct {
ID uint64 `json:"id" yaml:"id"` // ID of the change
Type string `json:"type" yaml:"type"`
Data []byte `json:"data" yaml:"data"`
BlockNum uint64 `json:"block_num" yaml:"block_num"` // Claimed mainchain block number when the infomation was queried
Initiator sdk.AccAddress `json:"initiator" yaml:"initiator"`
Voters []sdk.ValAddress `json:"voters" yaml:"voters"`
Status ChangeStatus `json:"change_status" yaml:"change_status"` // Status of the Change {Pending, Active, Passed, Rejected}
SubmitTime time.Time `json:"submit_time" yaml:"submit_time"` // Time of the block where TxGovSubmitChange was included
VotingEndTime time.Time `json:"voting_end_time" yaml:"voting_end_time"` // Time that the VotingPeriod for this change will end and votes will be tallied
Rewardable bool `json:"rewardable" yaml:"rewardable"`
}
// NewChange creates a new Change instance
func NewChange(id uint64, changeType string, data []byte, blockNum uint64, submitTime, votingEndTime time.Time, initiatorAddr sdk.AccAddress) Change {
return Change{
ID: id,
Type: changeType,
Data: data,
BlockNum: blockNum,
Initiator: initiatorAddr,
Status: StatusActive,
SubmitTime: submitTime,
VotingEndTime: votingEndTime,
}
}
// String implements stringer interface
func (c Change) String() string {
return fmt.Sprintf(`Change: %d, Type: %s, BlockNum: %d Initiator: %s, Rewardable: %t, Status: %s, Submit Time: %s, Voting End Time: %s.`,
c.ID, c.Type, c.BlockNum, c.Initiator, c.Rewardable, c.Status, c.SubmitTime, c.VotingEndTime,
)
}
// Changes is an array of change
type Changes []Change
// String implements stringer interface
func (changes Changes) String() string {
out := "ID - (Status) [Type]\n"
for _, change := range changes {
out += fmt.Sprintf("%d - (%s) [%s]\n",
change.ID, change.Status,
change.Type)
}
return strings.TrimSpace(out)
}
type (
// ChangeQueue defines a queue for change ids
ChangeQueue []uint64
// ChangeStatus is a type alias that represents a change status as a byte
ChangeStatus byte
)
// Valid Change statuses
const (
StatusNil ChangeStatus = 0x00
StatusActive ChangeStatus = 0x01
StatusPassed ChangeStatus = 0x02
StatusFailed ChangeStatus = 0x03
)
// ChangeStatusFromString turns a string into a ChangeStatus
func ChangeStatusFromString(str string) (ChangeStatus, error) {
switch str {
case "VotingPeriod":
return StatusActive, nil
case "Passed":
return StatusPassed, nil
case "Failed":
return StatusFailed, nil
case "":
return StatusNil, nil
default:
return ChangeStatus(0xff), fmt.Errorf("'%s' is not a valid change status", str)
}
}
// ValidChangeStatus returns true if the change status is valid and false
// otherwise.
func ValidChangeStatus(status ChangeStatus) bool {
if status == StatusActive ||
status == StatusPassed ||
status == StatusFailed {
return true
}
return false
}
// Marshal needed for protobuf compatibility
func (status ChangeStatus) Marshal() ([]byte, error) {
return []byte{byte(status)}, nil
}
// Unmarshal needed for protobuf compatibility
func (status *ChangeStatus) Unmarshal(data []byte) error {
*status = ChangeStatus(data[0])
return nil
}
// MarshalJSON Marshals to JSON using string representation of the status
func (status ChangeStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(status.String())
}
// UnmarshalJSON Unmarshals from JSON assuming Bech32 encoding
func (status *ChangeStatus) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
bz2, err := ChangeStatusFromString(s)
if err != nil {
return err
}
*status = bz2
return nil
}
// String implements the Stringer interface.
func (status ChangeStatus) String() string {
switch status {
case StatusActive:
return "VotingPeriod"
case StatusPassed:
return "Passed"
case StatusFailed:
return "Failed"
default:
return ""
}
}
// Format implements the fmt.Formatter interface.
// nolint: errcheck
func (status ChangeStatus) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(status.String()))
default:
// TODO: Do this conversion more directly
s.Write([]byte(fmt.Sprintf("%v", byte(status))))
}
}