-
Notifications
You must be signed in to change notification settings - Fork 10
/
proposal.go
177 lines (155 loc) · 4.27 KB
/
proposal.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
172
173
174
175
176
177
package distribution
import (
"time"
"github.com/ofgp/ofgp-core/dgwdb"
"github.com/ofgp/ofgp-core/log"
"github.com/ofgp/ofgp-core/primitives"
pb "github.com/ofgp/ofgp-core/proto"
"github.com/spf13/viper"
)
const (
proposalStatus = iota
proposalNew
proposalDealing
proposalSuccess
proposalFailed
)
var (
logger = log.New(viper.GetString("loglevel"), "dist")
)
// Output 一笔提案里面的一个输出
type Output struct {
Address string `json:"address"`
Amount int64 `json:"amount"`
}
// Proposal 提案内容
type Proposal struct {
Data []Output `json:"data"`
Chain string `json:"chain"`
ID string `json:"id"`
}
type DistributionInfo struct {
Proposal *Proposal `json:"proposal"`
CreateTime time.Time `json:"create_time"`
Status int `json:"status"`
}
// ProposalManager 提案管理,负责增删查
type ProposalManager struct {
db *dgwdb.LDBDatabase
ts *primitives.TxStore
}
// NewProposalManager 新建一个ProposalManager实例并返回
func NewProposalManager(db *dgwdb.LDBDatabase, ts *primitives.TxStore) *ProposalManager {
pm := &ProposalManager{
db: db,
ts: ts,
}
return pm
}
// LoadFromDB 把保存在磁盘里面的未完成的proposal读取到内存
func (pm *ProposalManager) LoadFromDB() {
diList := getAllDistributionProposal(pm.db)
for _, di := range diList {
if di.Status != proposalSuccess {
watchedTx := genWatchedTx(di.Proposal)
pm.ts.AddWatchedTx(watchedTx)
// 重启之后从磁盘读取,如果之前状态是处理中,修改为失败
if di.Status == proposalDealing {
pm.setStatus(di.Proposal.ID, proposalFailed)
}
}
}
}
// AddProposal 新增一个提案
func (pm *ProposalManager) AddProposal(p *Proposal) bool {
old, _ := getDistributionProposal(pm.db, p.ID)
if old != nil {
return false
}
di := &DistributionInfo{
Proposal: p,
CreateTime: time.Now(),
Status: proposalNew,
}
setDistributionProposal(pm.db, di)
watchedTx := genWatchedTx(p)
pm.ts.AddWatchedTx(watchedTx)
return true
}
// DeleteProposal 删除一个提案, 返回是否删除完成
func (pm *ProposalManager) DeleteProposal(proposalID string) bool {
info, err := getDistributionProposal(pm.db, proposalID)
if err != nil {
return true
}
if info.Status == proposalFailed || info.Status == proposalNew {
delDistributionProposal(pm.db, proposalID)
return true
}
return false
}
// GetProposal 查找指定提案
func (pm *ProposalManager) GetProposal(proposalID string) *DistributionInfo {
info, err := getDistributionProposal(pm.db, proposalID)
if err != nil {
return nil
}
return info
}
// ListProposal 返回所有的提案
func (pm *ProposalManager) ListProposal() []*DistributionInfo {
return getAllDistributionProposal(pm.db)
}
// ExecuteProposal 执行指定的提案
func (pm *ProposalManager) ExecuteProposal(proposalID string) {
currStatus := pm.getStatus(proposalID)
if currStatus != proposalFailed && currStatus != proposalNew {
return
}
pm.ts.WatchedTxToFresh("DistributionTx" + proposalID)
pm.setStatus(proposalID, proposalDealing)
}
func (pm *ProposalManager) getStatus(proposalID string) int {
info, err := getDistributionProposal(pm.db, proposalID)
if err != nil {
return proposalStatus
}
return info.Status
}
func (pm *ProposalManager) setStatus(proposalID string, status int) {
logger.Debug("set proposal status", "proposal", proposalID, "status", status)
info, err := getDistributionProposal(pm.db, proposalID)
if err != nil {
return
}
info.Status = status
setDistributionProposal(pm.db, info)
}
// SetFailed 设置提案状态为执行失败
func (pm *ProposalManager) SetFailed(proposalID string) {
pm.setStatus(proposalID, proposalFailed)
}
// SetSuccess 设置提案状态为执行成功
func (pm *ProposalManager) SetSuccess(proposalID string) {
pm.setStatus(proposalID, proposalSuccess)
}
// SetDealing 设置提案状态为执行中
func (pm *ProposalManager) SetDealing(proposalID string) {
pm.setStatus(proposalID, proposalDealing)
}
func genWatchedTx(p *Proposal) *pb.WatchedTxInfo {
res := &pb.WatchedTxInfo{
Txid: "DistributionTx" + p.ID,
From: p.Chain,
To: p.Chain,
Amount: 0,
}
for _, o := range p.Data {
res.RechargeList = append(res.RechargeList, &pb.AddressInfo{
Address: o.Address,
Amount: o.Amount,
})
res.Amount += o.Amount
}
return res
}