OSDN Git Service

Merge pull request #35 from Bytom/dev_dpos_vote_simplification
[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
400         result = result[:delegateNum]
401         return result
402 }
403
404 func (v *Vote) GetAddressBalance(address string) uint64 {
405
406         if votes, ok := v.AddressBalances[address]; ok {
407                 return votes
408         }
409
410         return 0
411 }
412
413 type control struct {
414         BlockHeight uint64  `json:"block_height"`
415         BlockHash   bc.Hash `json:"block_hash"`
416 }
417
418 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
419         data, err := ioutil.ReadFile(fileName)
420         if err != nil {
421                 return err
422         }
423         c := &control{}
424
425         if err = json.Unmarshal(data, c); err != nil {
426                 return err
427         }
428
429         *blockHash = c.BlockHash
430         *blockHeight = c.BlockHeight
431         return nil
432 }
433
434 func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error {
435
436         fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
437         if err != nil {
438                 return err
439         }
440         defer fileObj.Close()
441
442         c := control{
443                 BlockHeight: blockHeight,
444                 BlockHash:   blockHash,
445         }
446
447         var data []byte
448
449         if data, err = json.Marshal(&c); err != nil {
450                 return err
451         }
452
453         if _, err = fileObj.Write(data); err != nil {
454                 return err
455         }
456
457         return nil
458 }
459
460 func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
461         v.lockVoter.Lock()
462         defer v.lockVoter.Unlock()
463
464         mapBalance := make(map[string]int64)
465
466         for _, value := range addressBalance {
467                 if value.Balance == 0 {
468                         continue
469                 }
470                 mapBalance[value.Address] += value.Balance
471         }
472         for addr, balance := range mapBalance {
473                 v.updateAddressBalance(addr, balance)
474         }
475 }
476
477 func (v *Vote) updateAddressBalance(address string, value int64) {
478         if val, ok := v.AddressBalances[address]; ok {
479                 banlance := int64(val) + value
480                 if banlance < 0 {
481                         cmn.Exit("The balance was negative")
482                 }
483                 if banlance == 0 {
484                         delete(v.AddressBalances, address)
485                 } else {
486                         v.AddressBalances[address] = uint64(banlance)
487                 }
488         } else {
489                 if value < 0 {
490                         cmn.Exit("The balance was negative")
491                 }
492                 if value > 0 {
493                         v.AddressBalances[address] = uint64(value)
494                 }
495         }
496 }
497
498 func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
499         v.lockHashHeightInvalidVote.Lock()
500         defer v.lockHashHeightInvalidVote.Unlock()
501         v.HashHeightInvalidVote[hash] = height
502 }
503 func (v *Vote) DeleteInvalidVote(height uint64) {
504         v.lockHashHeightInvalidVote.Lock()
505         defer v.lockHashHeightInvalidVote.Unlock()
506         for k, value := range v.HashHeightInvalidVote {
507                 if value <= height {
508                         delete(v.HashHeightInvalidVote, k)
509                 }
510         }
511 }
512
513 func (v *Vote) GetOldBlockHeight() uint64 {
514         return v.oldBlockHeight
515 }
516
517 func (v *Vote) GetOldBlockHash() bc.Hash {
518         return v.oldBlockHash
519 }
520
521 func (v *Vote) GetDelegate(name string) string {
522         v.lockVoter.Lock()
523         defer v.lockVoter.Unlock()
524
525         if delegate, ok := v.NameDelegate[name]; ok {
526                 return delegate
527         }
528         return ""
529 }
530
531 func (v *Vote) GetDelegateName(address string) string {
532         v.lockVoter.Lock()
533         defer v.lockVoter.Unlock()
534         if name, ok := v.DelegateName[address]; ok {
535                 return name
536         }
537         return ""
538 }
539
540 func (v *Vote) HaveVote(voter string, delegate string) bool {
541         v.lockVoter.Lock()
542         defer v.lockVoter.Unlock()
543
544         if voters, ok := v.DelegateVoters[delegate]; ok {
545                 if _, ok := voters[voter]; ok {
546                         return true
547                 }
548         }
549
550         return false
551 }
552
553 func (v *Vote) HaveDelegate(name string, delegate string) bool {
554         v.lockVoter.Lock()
555         defer v.lockVoter.Unlock()
556
557         if n, ok := v.DelegateName[delegate]; ok {
558                 if n == name {
559                         return true
560                 }
561         }
562
563         return false
564 }
565
566 func (v *Vote) GetVotedDelegates(voter string) []string {
567         v.lockVoter.Lock()
568         defer v.lockVoter.Unlock()
569         var results []string
570         if delegates, ok := v.VoterDelegates[voter]; ok {
571                 for delegate, _ := range delegates {
572                         results = append(results, delegate)
573                 }
574         }
575         return results
576 }
577
578 func (v *Vote) ListDelegates() map[string]string {
579         v.lockVoter.Lock()
580         defer v.lockVoter.Unlock()
581         return v.NameDelegate
582 }
583
584 func (v *Vote) GetDelegateVotes(delegate string) uint64 {
585         votes := uint64(0)
586         if voters, ok := v.DelegateVoters[delegate]; ok {
587                 for voter := range voters {
588                         votes += v.GetAddressBalance(voter)
589                 }
590         }
591         return votes
592 }
593
594 func (v *Vote) GetDelegateVoters(delegate string) []string {
595         v.lockVoter.Lock()
596         defer v.lockVoter.Unlock()
597
598         var result []string
599
600         if voters, ok := v.DelegateVoters[delegate]; ok {
601                 for voter := range voters {
602                         result = append(result, voter)
603                 }
604         }
605
606         return result
607 }