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
58 func newVote(blockHeight uint64, blockHash bc.Hash) (*Vote, error) {
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 err := vote.New(blockHeight, blockHash)
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)
82 if err := cmn.EnsureDir(v.filePath, 0700); err != nil {
86 if err := v.load(blockHeight, blockHash); err != nil {
93 func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
95 defer v.lockRegister.Unlock()
97 if _, ok := v.DelegateName[delegateAddress]; ok {
98 v.AddInvalidVote(hash, height)
101 if _, ok := v.NameDelegate[delegateName]; ok {
102 v.AddInvalidVote(hash, height)
105 v.DelegateName[delegateAddress] = delegateName
106 v.NameDelegate[delegateName] = delegateAddress
110 func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
112 defer v.lockVoter.Unlock()
116 if delegates, ok := v.VoterDelegates[voterAddress]; ok {
117 votes = len(delegates)
120 if votes+len(delegates) > consensus.MaxNumberOfVotes {
121 v.AddInvalidVote(hash, height)
125 for _, delegate := range delegates {
126 if _, ok := v.DelegateName[delegate]; !ok {
127 v.AddInvalidVote(hash, height)
130 if voters, ok := v.DelegateVoters[delegate]; ok {
131 if _, ok = voters[voterAddress]; ok {
132 v.AddInvalidVote(hash, height)
135 voters[voterAddress] = true
136 v.DelegateVoters[delegate] = voters
139 voters := make(map[string]bool)
140 voters[voterAddress] = true
141 v.DelegateVoters[delegate] = voters
143 if dg, ok := v.VoterDelegates[voterAddress]; ok {
145 v.VoterDelegates[voterAddress] = dg
147 dg := make(map[string]bool)
149 v.VoterDelegates[voterAddress] = dg
155 func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
157 defer v.lockVoter.Unlock()
159 for _, delegate := range delegates {
160 if voters, ok := v.DelegateVoters[delegate]; ok {
161 if _, ok = voters[voterAddress]; !ok {
162 v.AddInvalidVote(hash, height)
165 if len(voters) == 1 {
166 delete(v.DelegateVoters, delegate)
168 delete(v.DelegateVoters[delegate], voterAddress)
172 v.AddInvalidVote(hash, height)
177 if item, ok := v.VoterDelegates[voterAddress]; ok {
178 for _, delegate := range delegates {
179 delete(v.VoterDelegates[voterAddress], delegate)
182 delete(v.VoterDelegates, voterAddress)
189 func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error {
190 if err := v.repairFile(blockHeight, blockHash); err != nil {
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())
202 func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
203 if blockHeight == 0 {
206 if err := v.Write(blockHash); err != nil {
210 if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil {
216 blockHeightTemp uint64
217 blockHashTemp bc.Hash
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")
225 v.Delete(blockHashTemp)
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"`
241 func (v *Vote) Write(blockHash bc.Hash) error {
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,
252 fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
256 defer fileObj.Close()
260 if data, err = json.Marshal(&f); err != nil {
264 if _, err = fileObj.Write(data); err != nil {
271 func (v *Vote) read() error {
273 if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil {
277 data, err := ioutil.ReadFile(v.forgerFileName + "-" + v.oldBlockHash.String())
284 if err = json.Unmarshal(data, f); err != nil {
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
299 func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error {
301 cmn.EnsureDir(v.filePath, 0700)
303 fileName := v.controlFileName + "-temp"
306 blockHeightTmp uint64
310 if cmn.FileExists(fileName) {
311 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
314 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
315 os.Rename(fileName, v.controlFileName)
321 fileName = v.controlFileName + "-old"
323 if cmn.FileExists(fileName) {
324 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
327 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
328 os.Rename(fileName, v.controlFileName)
334 fileName = v.controlFileName
335 if cmn.FileExists(fileName) {
336 if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
339 if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
344 return fmt.Errorf("repairFile fail in %d height", blockHeightTmp)
347 func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate {
349 defer v.lockVoter.Unlock()
351 var result []Delegate
352 for k, value := range v.DelegateVoters {
354 for address := range value {
355 votes += v.GetAddressBalance(address)
357 if v.GetAddressBalance(k) >= minHoldBalance {
358 result = append(result, Delegate{k, votes})
361 sort.Sort(DelegateWrapper{result, func(p, q *Delegate) bool {
362 if p.Votes < q.Votes {
364 } else if p.Votes > q.Votes {
367 return bytes.Compare([]byte(p.DelegateAddress), []byte(q.DelegateAddress)) > 0
370 for k := range v.DelegateName {
371 if uint64(len(result)) >= delegateNum {
374 if v.GetAddressBalance(k) < consensus.MinHoldBalance {
377 if _, ok := v.DelegateVoters[k]; !ok {
378 result = append(result, Delegate{k, 0})
381 if uint64(len(result)) <= delegateNum {
384 result = result[:delegateNum]
388 func (v *Vote) GetAddressBalance(address string) uint64 {
390 if votes, ok := v.AddressBalances[address]; ok {
397 type control struct {
398 BlockHeight uint64 `json:"block_height"`
399 BlockHash bc.Hash `json:"block_hash"`
402 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
403 data, err := ioutil.ReadFile(fileName)
409 if err = json.Unmarshal(data, c); err != nil {
413 *blockHash = c.BlockHash
414 *blockHeight = c.BlockHeight
418 func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error {
420 fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
424 defer fileObj.Close()
427 BlockHeight: blockHeight,
428 BlockHash: blockHash,
433 if data, err = json.Marshal(&c); err != nil {
437 if _, err = fileObj.Write(data); err != nil {
444 func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
446 defer v.lockVoter.Unlock()
448 mapBalance := make(map[string]int64)
450 for _, value := range addressBalance {
451 if value.Balance == 0 {
454 mapBalance[value.Address] += value.Balance
456 for addr, balance := range mapBalance {
457 v.updateAddressBalance(addr, balance)
461 func (v *Vote) updateAddressBalance(address string, value int64) {
462 if val, ok := v.AddressBalances[address]; ok {
463 banlance := int64(val) + value
465 cmn.Exit(fmt.Sprintf("The balance was negative: %s: %d", address, value))
468 delete(v.AddressBalances, address)
470 v.AddressBalances[address] = uint64(banlance)
474 cmn.Exit(fmt.Sprintf("The balance was negative: %s: %d", address, value))
477 v.AddressBalances[address] = uint64(value)
482 func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
483 v.lockHashHeightInvalidVote.Lock()
484 defer v.lockHashHeightInvalidVote.Unlock()
485 v.HashHeightInvalidVote[hash] = height
487 func (v *Vote) DeleteInvalidVote(height uint64) {
488 v.lockHashHeightInvalidVote.Lock()
489 defer v.lockHashHeightInvalidVote.Unlock()
490 for k, value := range v.HashHeightInvalidVote {
492 delete(v.HashHeightInvalidVote, k)
497 func (v *Vote) GetOldBlockHeight() uint64 {
498 return v.oldBlockHeight
501 func (v *Vote) GetOldBlockHash() bc.Hash {
502 return v.oldBlockHash
505 func (v *Vote) GetDelegate(name string) string {
507 defer v.lockVoter.Unlock()
509 if delegate, ok := v.NameDelegate[name]; ok {
515 func (v *Vote) GetDelegateName(address string) string {
517 defer v.lockVoter.Unlock()
518 if name, ok := v.DelegateName[address]; ok {
524 func (v *Vote) HaveVote(voter string, delegate string) bool {
526 defer v.lockVoter.Unlock()
528 if voters, ok := v.DelegateVoters[delegate]; ok {
529 if _, ok := voters[voter]; ok {
537 func (v *Vote) HaveDelegate(name string, delegate string) bool {
539 defer v.lockVoter.Unlock()
541 if n, ok := v.DelegateName[delegate]; ok {
550 func (v *Vote) GetVotedDelegates(voter string) []string {
552 defer v.lockVoter.Unlock()
554 if delegates, ok := v.VoterDelegates[voter]; ok {
555 for delegate, _ := range delegates {
556 results = append(results, delegate)
562 func (v *Vote) ListDelegates() map[string]string {
564 defer v.lockVoter.Unlock()
565 return v.NameDelegate
568 func (v *Vote) GetDelegateVotes(delegate string) uint64 {
570 if voters, ok := v.DelegateVoters[delegate]; ok {
571 for voter := range voters {
572 votes += v.GetAddressBalance(voter)
578 func (v *Vote) GetDelegateVoters(delegate string) []string {
580 defer v.lockVoter.Unlock()
584 if voters, ok := v.DelegateVoters[delegate]; ok {
585 for voter := range voters {
586 result = append(result, voter)