13 cmn "github.com/tendermint/tmlibs/common"
15 "github.com/vapor/config"
16 "github.com/vapor/consensus"
17 engine "github.com/vapor/consensus/consensus"
18 "github.com/vapor/protocol/bc"
23 DelegateFile = "delegate.dat"
24 BalanceFile = "balance.dat"
25 ControlFile = "control.dat"
26 InvalidVoteTxFile = "invalidvotetx.dat"
27 DelegateMultiAddressFile = "delegatemultiaddress.dat"
29 ForgerFile = "forger.data"
33 DelegateVoters map[string]map[string]bool
34 VoterDelegates map[string]map[string]bool
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
45 delegateFileName string
47 balanceFileName string
48 controlFileName string
49 invalidVoteTxFileName string
50 delegateMultiaddressName string
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),
69 func newVote(blockHeight uint64, blockHash bc.Hash) (*Vote, error) {
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),
80 if err := vote.New(blockHeight, blockHash); err != nil {
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)
96 if err := cmn.EnsureDir(v.filePath, 0700); err != nil {
100 if err := v.load(blockHeight, blockHash); err != nil {
107 func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
108 v.lockRegister.Lock()
109 defer v.lockRegister.Unlock()
111 if _, ok := v.DelegateName[delegateAddress]; ok {
112 v.AddInvalidVote(hash, height)
115 if _, ok := v.NameDelegate[delegateName]; ok {
116 v.AddInvalidVote(hash, height)
119 v.DelegateName[delegateAddress] = delegateName
120 v.NameDelegate[delegateName] = delegateAddress
124 func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
126 defer v.lockVoter.Unlock()
130 if delegates, ok := v.VoterDelegates[voterAddress]; ok {
131 votes = len(delegates)
134 if votes+len(delegates) > consensus.MaxNumberOfVotes {
135 v.AddInvalidVote(hash, height)
139 for _, delegate := range delegates {
140 if _, ok := v.DelegateName[delegate]; !ok {
141 v.AddInvalidVote(hash, height)
144 if voters, ok := v.DelegateVoters[delegate]; ok {
145 if _, ok = voters[voterAddress]; ok {
146 v.AddInvalidVote(hash, height)
149 voters[voterAddress] = true
150 v.DelegateVoters[delegate] = voters
153 voters := make(map[string]bool)
154 voters[voterAddress] = true
155 v.DelegateVoters[delegate] = voters
157 if dg, ok := v.VoterDelegates[voterAddress]; ok {
159 v.VoterDelegates[voterAddress] = dg
161 dg := make(map[string]bool)
163 v.VoterDelegates[voterAddress] = dg
169 func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
171 defer v.lockVoter.Unlock()
173 for _, delegate := range delegates {
174 if voters, ok := v.DelegateVoters[delegate]; ok {
175 if _, ok = voters[voterAddress]; !ok {
176 v.AddInvalidVote(hash, height)
179 if len(voters) == 1 {
180 delete(v.DelegateVoters, delegate)
182 delete(v.DelegateVoters[delegate], voterAddress)
186 v.AddInvalidVote(hash, height)
191 if item, ok := v.VoterDelegates[voterAddress]; ok {
192 for _, delegate := range delegates {
193 delete(v.VoterDelegates[voterAddress], delegate)
196 delete(v.VoterDelegates, voterAddress)
203 func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error {
204 if err := v.repairFile(blockHeight, blockHash); err != nil {
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())
216 func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
217 if blockHeight == 0 {
220 if err := v.Write(blockHash); err != nil {
224 if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil {
230 blockHeightTemp uint64
231 blockHashTemp bc.Hash
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")
239 v.Delete(blockHashTemp)
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"`
255 func (v *Vote) Write(blockHash bc.Hash) error {
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,
266 fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
270 defer fileObj.Close()
274 if data, err = json.Marshal(&f); err != nil {
278 if _, err = fileObj.Write(data); err != nil {
285 func (v *Vote) read() error {
287 if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil {
291 data, err := ioutil.ReadFile(v.forgerFileName + "-" + v.oldBlockHash.String())
298 if err = json.Unmarshal(data, f); err != nil {
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
313 func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error {
315 cmn.EnsureDir(v.filePath, 0700)
317 fileName := v.controlFileName + "-temp"
320 blockHeightTmp uint64
324 if cmn.FileExists(fileName) {
325 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
328 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
329 os.Rename(fileName, v.controlFileName)
335 fileName = v.controlFileName + "-old"
337 if cmn.FileExists(fileName) {
338 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
341 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
342 os.Rename(fileName, v.controlFileName)
348 fileName = v.controlFileName
349 if cmn.FileExists(fileName) {
350 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
353 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
358 return fmt.Errorf("repairFile fail in %d height", blockHeightTmp)
361 func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate {
363 defer v.lockVoter.Unlock()
365 var result []Delegate
366 for k, value := range v.DelegateVoters {
368 for address := range value {
369 votes += v.GetAddressBalance(address)
371 if v.GetAddressBalance(k) >= minHoldBalance {
372 result = append(result, Delegate{k, votes})
375 sort.Sort(DelegateWrapper{result, func(p, q *Delegate) bool {
376 if p.Votes < q.Votes {
378 } else if p.Votes > q.Votes {
381 if strings.Compare(p.DelegateAddress, p.DelegateAddress) >= 0 {
388 for k := range v.DelegateName {
389 if uint64(len(result)) >= delegateNum {
392 if v.GetAddressBalance(k) < consensus.MinHoldBalance {
395 if _, ok := v.DelegateVoters[k]; !ok {
396 result = append(result, Delegate{k, 0})
399 if uint64(len(result)) <= delegateNum {
402 result = result[:delegateNum]
406 func (v *Vote) GetAddressBalance(address string) uint64 {
408 if votes, ok := v.AddressBalances[address]; ok {
415 type control struct {
416 BlockHeight uint64 `json:"block_height"`
417 BlockHash bc.Hash `json:"block_hash"`
420 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
421 data, err := ioutil.ReadFile(fileName)
427 if err = json.Unmarshal(data, c); err != nil {
431 *blockHash = c.BlockHash
432 *blockHeight = c.BlockHeight
436 func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error {
438 fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
442 defer fileObj.Close()
445 BlockHeight: blockHeight,
446 BlockHash: blockHash,
451 if data, err = json.Marshal(&c); err != nil {
455 if _, err = fileObj.Write(data); err != nil {
462 func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
464 defer v.lockVoter.Unlock()
466 mapBalance := make(map[string]int64)
468 for _, value := range addressBalance {
469 if value.Balance == 0 {
472 mapBalance[value.Address] += value.Balance
474 for addr, balance := range mapBalance {
475 v.updateAddressBalance(addr, balance)
479 func (v *Vote) updateAddressBalance(address string, value int64) {
480 if val, ok := v.AddressBalances[address]; ok {
481 banlance := int64(val) + value
483 cmn.Exit("The balance was negative")
486 delete(v.AddressBalances, address)
488 v.AddressBalances[address] = uint64(banlance)
492 cmn.Exit("The balance was negative")
495 v.AddressBalances[address] = uint64(value)
500 func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
501 v.lockHashHeightInvalidVote.Lock()
502 defer v.lockHashHeightInvalidVote.Unlock()
503 v.HashHeightInvalidVote[hash] = height
505 func (v *Vote) DeleteInvalidVote(height uint64) {
506 v.lockHashHeightInvalidVote.Lock()
507 defer v.lockHashHeightInvalidVote.Unlock()
508 for k, value := range v.HashHeightInvalidVote {
510 delete(v.HashHeightInvalidVote, k)
515 func (v *Vote) GetOldBlockHeight() uint64 {
516 return v.oldBlockHeight
519 func (v *Vote) GetOldBlockHash() bc.Hash {
520 return v.oldBlockHash
523 func (v *Vote) GetDelegate(name string) string {
525 defer v.lockVoter.Unlock()
527 if delegate, ok := v.NameDelegate[name]; ok {
533 func (v *Vote) GetDelegateName(address string) string {
535 defer v.lockVoter.Unlock()
536 if name, ok := v.DelegateName[address]; ok {
542 func (v *Vote) HaveVote(voter string, delegate string) bool {
544 defer v.lockVoter.Unlock()
546 if voters, ok := v.DelegateVoters[delegate]; ok {
547 if _, ok := voters[voter]; ok {
555 func (v *Vote) HaveDelegate(name string, delegate string) bool {
557 defer v.lockVoter.Unlock()
559 if n, ok := v.DelegateName[delegate]; ok {
568 func (v *Vote) GetVotedDelegates(voter string) []string {
570 defer v.lockVoter.Unlock()
572 if delegates, ok := v.VoterDelegates[voter]; ok {
573 for delegate, _ := range delegates {
574 results = append(results, delegate)
580 func (v *Vote) ListDelegates() map[string]string {
582 defer v.lockVoter.Unlock()
583 return v.NameDelegate
586 func (v *Vote) GetDelegateVotes(delegate string) uint64 {
588 if voters, ok := v.DelegateVoters[delegate]; ok {
589 for voter := range voters {
590 votes += v.GetAddressBalance(voter)
596 func (v *Vote) GetDelegateVoters(delegate string) []string {
598 defer v.lockVoter.Unlock()
602 if voters, ok := v.DelegateVoters[delegate]; ok {
603 for voter := range voters {
604 result = append(result, voter)