OSDN Git Service

modify bug
[bytom/vapor.git] / consensus / consensus / dpos / vote.go
1 package dpos
2
3 import (
4         "encoding/json"
5         "fmt"
6         "io/ioutil"
7         "os"
8         "path/filepath"
9         "sort"
10         "strings"
11         "sync"
12
13         cmn "github.com/tendermint/tmlibs/common"
14
15         "github.com/vapor/config"
16         "github.com/vapor/consensus"
17         engine "github.com/vapor/consensus/consensus"
18         "github.com/vapor/protocol/bc"
19 )
20
21 const (
22         VoteFile                 = "vote.dat"
23         DelegateFile             = "delegate.dat"
24         BalanceFile              = "balance.dat"
25         ControlFile              = "control.dat"
26         InvalidVoteTxFile        = "invalidvotetx.dat"
27         DelegateMultiAddressFile = "delegatemultiaddress.dat"
28
29         ForgerFile = "forger.data"
30 )
31
32 type Vote struct {
33         DelegateVoters            map[string]map[string]bool
34         VoterDelegates            map[string]map[string]bool
35         lockVoter                 sync.Mutex
36         DelegateName              map[string]string
37         NameDelegate              map[string]string
38         lockRegister              sync.Mutex
39         HashHeightInvalidVote     map[bc.Hash]uint64
40         lockHashHeightInvalidVote sync.Mutex
41         AddressBalances           map[string]uint64
42         DelegateMultiaddress      map[string]uint64
43
44         filePath                 string
45         delegateFileName         string
46         voteFileName             string
47         balanceFileName          string
48         controlFileName          string
49         invalidVoteTxFileName    string
50         delegateMultiaddressName string
51
52         forgerFileName string
53
54         oldBlockHeight uint64
55         oldBlockHash   bc.Hash
56 }
57
58 /*
59 var DposVote = Vote{
60         DelegateVoters:        make(map[string]map[string]bool),
61         VoterDelegates:        make(map[string]map[string]bool),
62         DelegateName:          make(map[string]string),
63         NameDelegate:          make(map[string]string),
64         HashHeightInvalidVote: make(map[bc.Hash]uint64),
65         AddressBalances:       make(map[string]uint64),
66         DelegateMultiaddress:  make(map[string]uint64),
67 }
68 */
69 func newVote(blockHeight uint64, blockHash bc.Hash) (*Vote, error) {
70         vote := &Vote{
71                 DelegateVoters:        make(map[string]map[string]bool),
72                 VoterDelegates:        make(map[string]map[string]bool),
73                 DelegateName:          make(map[string]string),
74                 NameDelegate:          make(map[string]string),
75                 HashHeightInvalidVote: make(map[bc.Hash]uint64),
76                 AddressBalances:       make(map[string]uint64),
77                 DelegateMultiaddress:  make(map[string]uint64),
78         }
79
80         if err := vote.New(blockHeight, blockHash); err != nil {
81                 return nil, err
82         }
83
84         return vote, nil
85 }
86
87 func (v *Vote) New(blockHeight uint64, blockHash bc.Hash) error {
88         v.filePath = filepath.Join(config.CommonConfig.RootDir, "dpos")
89         v.delegateFileName = filepath.Join(v.filePath, DelegateFile)
90         v.balanceFileName = filepath.Join(v.filePath, BalanceFile)
91         v.controlFileName = filepath.Join(v.filePath, ControlFile)
92         v.invalidVoteTxFileName = filepath.Join(v.filePath, InvalidVoteTxFile)
93         v.delegateMultiaddressName = filepath.Join(v.filePath, DelegateMultiAddressFile)
94         v.forgerFileName = filepath.Join(v.filePath, ForgerFile)
95         if blockHeight == 0 {
96                 if err := cmn.EnsureDir(v.filePath, 0700); err != nil {
97                         return err
98                 }
99         } else {
100                 if err := v.load(blockHeight, blockHash); err != nil {
101                         return err
102                 }
103         }
104         return nil
105 }
106
107 func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
108         v.lockRegister.Lock()
109         defer v.lockRegister.Unlock()
110
111         if _, ok := v.DelegateName[delegateAddress]; ok {
112                 v.AddInvalidVote(hash, height)
113                 return false
114         }
115         if _, ok := v.NameDelegate[delegateName]; ok {
116                 v.AddInvalidVote(hash, height)
117                 return false
118         }
119         v.DelegateName[delegateAddress] = delegateName
120         v.NameDelegate[delegateName] = delegateAddress
121         return true
122 }
123
124 func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
125         v.lockVoter.Lock()
126         defer v.lockVoter.Unlock()
127
128         votes := 0
129
130         if delegates, ok := v.VoterDelegates[voterAddress]; ok {
131                 votes = len(delegates)
132         }
133
134         if votes+len(delegates) > consensus.MaxNumberOfVotes {
135                 v.AddInvalidVote(hash, height)
136                 return false
137         }
138
139         for _, delegate := range delegates {
140                 if _, ok := v.DelegateName[delegate]; !ok {
141                         v.AddInvalidVote(hash, height)
142                         return false
143                 }
144                 if voters, ok := v.DelegateVoters[delegate]; ok {
145                         if _, ok = voters[voterAddress]; ok {
146                                 v.AddInvalidVote(hash, height)
147                                 return false
148                         } else {
149                                 voters[voterAddress] = true
150                                 v.DelegateVoters[delegate] = voters
151                         }
152                 } else {
153                         voters := make(map[string]bool)
154                         voters[voterAddress] = true
155                         v.DelegateVoters[delegate] = voters
156                 }
157                 if dg, ok := v.VoterDelegates[voterAddress]; ok {
158                         dg[delegate] = true
159                         v.VoterDelegates[voterAddress] = dg
160                 } else {
161                         dg := make(map[string]bool)
162                         dg[delegate] = true
163                         v.VoterDelegates[voterAddress] = dg
164                 }
165         }
166         return true
167 }
168
169 func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
170         v.lockVoter.Lock()
171         defer v.lockVoter.Unlock()
172
173         for _, delegate := range delegates {
174                 if voters, ok := v.DelegateVoters[delegate]; ok {
175                         if _, ok = voters[voterAddress]; !ok {
176                                 v.AddInvalidVote(hash, height)
177                                 return false
178                         } else {
179                                 if len(voters) == 1 {
180                                         delete(v.DelegateVoters, delegate)
181                                 } else {
182                                         delete(v.DelegateVoters[delegate], voterAddress)
183                                 }
184                         }
185                 } else {
186                         v.AddInvalidVote(hash, height)
187                         return false
188                 }
189         }
190
191         if item, ok := v.VoterDelegates[voterAddress]; ok {
192                 for _, delegate := range delegates {
193                         delete(v.VoterDelegates[voterAddress], delegate)
194                 }
195                 if len(item) == 0 {
196                         delete(v.VoterDelegates, voterAddress)
197                 }
198         }
199
200         return true
201 }
202
203 func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error {
204         if err := v.repairFile(blockHeight, blockHash); err != nil {
205                 return err
206         }
207         return v.read()
208 }
209
210 func (v *Vote) Delete(blockHash bc.Hash) {
211         os.Remove(v.delegateFileName + "-" + blockHash.String())
212         os.Remove(v.voteFileName + "-" + blockHash.String())
213         os.Remove(v.balanceFileName + "-" + blockHash.String())
214 }
215
216 func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
217         if blockHeight == 0 {
218                 return nil
219         }
220         if err := v.Write(blockHash); err != nil {
221                 return err
222         }
223
224         if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil {
225                 v.Delete(blockHash)
226                 return err
227         }
228
229         var (
230                 blockHeightTemp uint64
231                 blockHashTemp   bc.Hash
232         )
233
234         if err := v.ReadControlFile(&blockHeightTemp, &blockHashTemp, v.controlFileName); err != nil {
235                 os.Rename(v.controlFileName, v.controlFileName+"-old")
236                 os.Rename(v.controlFileName+"-temp", v.controlFileName)
237                 os.Remove(v.controlFileName + "-old")
238         } else {
239                 v.Delete(blockHashTemp)
240         }
241
242         return nil
243 }
244
245 type forger struct {
246         DelegateVoters        map[string]map[string]bool `json:"delegate_voters"`
247         VoterDelegates        map[string]map[string]bool `json:"voter_delegates"`
248         DelegateName          map[string]string          `json:"delegate_name"`
249         NameDelegate          map[string]string          `json:"name_delegate"`
250         HashHeightInvalidVote map[bc.Hash]uint64         `json:"hash_height_invalid_vote"`
251         AddressBalances       map[string]uint64          `json:"address_balance"`
252         DelegateMultiaddress  map[string]uint64          `json:"delegate_multiaddress"`
253 }
254
255 func (v *Vote) Write(blockHash bc.Hash) error {
256
257         f := forger{
258                 DelegateVoters:        v.DelegateVoters,
259                 VoterDelegates:        v.VoterDelegates,
260                 DelegateName:          v.DelegateName,
261                 NameDelegate:          v.NameDelegate,
262                 HashHeightInvalidVote: v.HashHeightInvalidVote,
263                 AddressBalances:       v.AddressBalances,
264                 DelegateMultiaddress:  v.DelegateMultiaddress,
265         }
266         fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
267         if err != nil {
268                 return err
269         }
270         defer fileObj.Close()
271
272         var data []byte
273
274         if data, err = json.Marshal(&f); err != nil {
275                 return err
276         }
277
278         if _, err = fileObj.Write(data); err != nil {
279                 return err
280         }
281
282         return nil
283 }
284
285 func (v *Vote) read() error {
286
287         if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil {
288                 return err
289         }
290
291         data, err := ioutil.ReadFile(v.forgerFileName + "-" + v.oldBlockHash.String())
292         if err != nil {
293                 return err
294         }
295
296         f := &forger{}
297
298         if err = json.Unmarshal(data, f); err != nil {
299                 return err
300         }
301
302         v.DelegateVoters = f.DelegateVoters
303         v.VoterDelegates = f.VoterDelegates
304         v.DelegateName = f.DelegateName
305         v.NameDelegate = f.NameDelegate
306         v.HashHeightInvalidVote = f.HashHeightInvalidVote
307         v.AddressBalances = f.AddressBalances
308         v.DelegateMultiaddress = f.DelegateMultiaddress
309
310         return nil
311 }
312
313 func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error {
314
315         cmn.EnsureDir(v.filePath, 0700)
316
317         fileName := v.controlFileName + "-temp"
318
319         var (
320                 blockHeightTmp uint64
321                 blockHashTmp   bc.Hash
322         )
323
324         if cmn.FileExists(fileName) {
325                 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
326                         return err
327                 }
328                 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
329                         os.Rename(fileName, v.controlFileName)
330                         return nil
331                 }
332                 os.Remove(fileName)
333         }
334
335         fileName = v.controlFileName + "-old"
336
337         if cmn.FileExists(fileName) {
338                 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
339                         return err
340                 }
341                 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
342                         os.Rename(fileName, v.controlFileName)
343                         return nil
344                 }
345                 os.Remove(fileName)
346         }
347
348         fileName = v.controlFileName
349         if cmn.FileExists(fileName) {
350                 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
351                         return err
352                 }
353                 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
354                         return nil
355                 }
356         }
357
358         return fmt.Errorf("repairFile fail in %d height", blockHeightTmp)
359 }
360
361 func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate {
362         v.lockVoter.Lock()
363         defer v.lockVoter.Unlock()
364
365         var result []Delegate
366         for k, value := range v.DelegateVoters {
367                 votes := uint64(0)
368                 for address := range value {
369                         votes += v.GetAddressBalance(address)
370                 }
371                 if v.GetAddressBalance(k) >= minHoldBalance {
372                         result = append(result, Delegate{k, votes})
373                 }
374         }
375         sort.Sort(DelegateWrapper{result, func(p, q *Delegate) bool {
376                 if p.Votes < q.Votes {
377                         return false
378                 } else if p.Votes > q.Votes {
379                         return true
380                 } else {
381                         if strings.Compare(p.DelegateAddress, p.DelegateAddress) >= 0 {
382                                 return false
383                         }
384                 }
385                 return true
386         }})
387
388         for k := range v.DelegateName {
389                 if uint64(len(result)) >= delegateNum {
390                         break
391                 }
392                 if v.GetAddressBalance(k) < consensus.MinHoldBalance {
393                         continue
394                 }
395                 if _, ok := v.DelegateVoters[k]; !ok {
396                         result = append(result, Delegate{k, 0})
397                 }
398         }
399         if uint64(len(result)) <= delegateNum {
400                 return result
401         }
402         result = result[:delegateNum]
403         return result
404 }
405
406 func (v *Vote) GetAddressBalance(address string) uint64 {
407
408         if votes, ok := v.AddressBalances[address]; ok {
409                 return votes
410         }
411
412         return 0
413 }
414
415 type control struct {
416         BlockHeight uint64  `json:"block_height"`
417         BlockHash   bc.Hash `json:"block_hash"`
418 }
419
420 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
421         data, err := ioutil.ReadFile(fileName)
422         if err != nil {
423                 return err
424         }
425         c := &control{}
426
427         if err = json.Unmarshal(data, c); err != nil {
428                 return err
429         }
430
431         *blockHash = c.BlockHash
432         *blockHeight = c.BlockHeight
433         return nil
434 }
435
436 func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error {
437
438         fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
439         if err != nil {
440                 return err
441         }
442         defer fileObj.Close()
443
444         c := control{
445                 BlockHeight: blockHeight,
446                 BlockHash:   blockHash,
447         }
448
449         var data []byte
450
451         if data, err = json.Marshal(&c); err != nil {
452                 return err
453         }
454
455         if _, err = fileObj.Write(data); err != nil {
456                 return err
457         }
458
459         return nil
460 }
461
462 func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
463         v.lockVoter.Lock()
464         defer v.lockVoter.Unlock()
465
466         mapBalance := make(map[string]int64)
467
468         for _, value := range addressBalance {
469                 if value.Balance == 0 {
470                         continue
471                 }
472                 mapBalance[value.Address] += value.Balance
473         }
474         for addr, balance := range mapBalance {
475                 v.updateAddressBalance(addr, balance)
476         }
477 }
478
479 func (v *Vote) updateAddressBalance(address string, value int64) {
480         if val, ok := v.AddressBalances[address]; ok {
481                 banlance := int64(val) + value
482                 if banlance < 0 {
483                         cmn.Exit("The balance was negative")
484                 }
485                 if banlance == 0 {
486                         delete(v.AddressBalances, address)
487                 } else {
488                         v.AddressBalances[address] = uint64(banlance)
489                 }
490         } else {
491                 if value < 0 {
492                         cmn.Exit("The balance was negative")
493                 }
494                 if value > 0 {
495                         v.AddressBalances[address] = uint64(value)
496                 }
497         }
498 }
499
500 func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
501         v.lockHashHeightInvalidVote.Lock()
502         defer v.lockHashHeightInvalidVote.Unlock()
503         v.HashHeightInvalidVote[hash] = height
504 }
505 func (v *Vote) DeleteInvalidVote(height uint64) {
506         v.lockHashHeightInvalidVote.Lock()
507         defer v.lockHashHeightInvalidVote.Unlock()
508         for k, value := range v.HashHeightInvalidVote {
509                 if value <= height {
510                         delete(v.HashHeightInvalidVote, k)
511                 }
512         }
513 }
514
515 func (v *Vote) GetOldBlockHeight() uint64 {
516         return v.oldBlockHeight
517 }
518
519 func (v *Vote) GetOldBlockHash() bc.Hash {
520         return v.oldBlockHash
521 }
522
523 func (v *Vote) GetDelegate(name string) string {
524         v.lockVoter.Lock()
525         defer v.lockVoter.Unlock()
526
527         if delegate, ok := v.NameDelegate[name]; ok {
528                 return delegate
529         }
530         return ""
531 }
532
533 func (v *Vote) GetDelegateName(address string) string {
534         v.lockVoter.Lock()
535         defer v.lockVoter.Unlock()
536         if name, ok := v.DelegateName[address]; ok {
537                 return name
538         }
539         return ""
540 }
541
542 func (v *Vote) HaveVote(voter string, delegate string) bool {
543         v.lockVoter.Lock()
544         defer v.lockVoter.Unlock()
545
546         if voters, ok := v.DelegateVoters[delegate]; ok {
547                 if _, ok := voters[voter]; ok {
548                         return true
549                 }
550         }
551
552         return false
553 }
554
555 func (v *Vote) HaveDelegate(name string, delegate string) bool {
556         v.lockVoter.Lock()
557         defer v.lockVoter.Unlock()
558
559         if n, ok := v.DelegateName[delegate]; ok {
560                 if n == name {
561                         return true
562                 }
563         }
564
565         return false
566 }
567
568 func (v *Vote) GetVotedDelegates(voter string) []string {
569         v.lockVoter.Lock()
570         defer v.lockVoter.Unlock()
571         var results []string
572         if delegates, ok := v.VoterDelegates[voter]; ok {
573                 for delegate, _ := range delegates {
574                         results = append(results, delegate)
575                 }
576         }
577         return results
578 }
579
580 func (v *Vote) ListDelegates() map[string]string {
581         v.lockVoter.Lock()
582         defer v.lockVoter.Unlock()
583         return v.NameDelegate
584 }
585
586 func (v *Vote) GetDelegateVotes(delegate string) uint64 {
587         votes := uint64(0)
588         if voters, ok := v.DelegateVoters[delegate]; ok {
589                 for voter := range voters {
590                         votes += v.GetAddressBalance(voter)
591                 }
592         }
593         return votes
594 }
595
596 func (v *Vote) GetDelegateVoters(delegate string) []string {
597         v.lockVoter.Lock()
598         defer v.lockVoter.Unlock()
599
600         var result []string
601
602         if voters, ok := v.DelegateVoters[delegate]; ok {
603                 for voter := range voters {
604                         result = append(result, voter)
605                 }
606         }
607
608         return result
609 }