OSDN Git Service

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