X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=consensus%2Fconsensus%2Fdpos%2Fvote.go;fp=consensus%2Fconsensus%2Fdpos%2Fvote.go;h=0000000000000000000000000000000000000000;hp=405d235b34928e6bbf1106ac57782c90a8a67992;hb=54373c1a3efe0e373ec1605840a4363e4b246c46;hpb=ee01d543fdfe1fd0a4d548965c66f7923ea7b062 diff --git a/consensus/consensus/dpos/vote.go b/consensus/consensus/dpos/vote.go deleted file mode 100644 index 405d235b..00000000 --- a/consensus/consensus/dpos/vote.go +++ /dev/null @@ -1,591 +0,0 @@ -package dpos - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" - "sync" - - cmn "github.com/tendermint/tmlibs/common" - - "github.com/vapor/config" - "github.com/vapor/consensus" - engine "github.com/vapor/consensus/consensus" - "github.com/vapor/protocol/bc" -) - -const ( - VoteFile = "vote.dat" - DelegateFile = "delegate.dat" - BalanceFile = "balance.dat" - ControlFile = "control.dat" - InvalidVoteTxFile = "invalidvotetx.dat" - DelegateMultiAddressFile = "delegatemultiaddress.dat" - - ForgerFile = "forger.data" -) - -type Vote struct { - DelegateVoters map[string]map[string]bool - VoterDelegates map[string]map[string]bool - lockVoter sync.Mutex - DelegateName map[string]string - NameDelegate map[string]string - lockRegister sync.Mutex - HashHeightInvalidVote map[bc.Hash]uint64 - lockHashHeightInvalidVote sync.Mutex - AddressBalances map[string]uint64 - DelegateMultiaddress map[string]uint64 - - filePath string - delegateFileName string - voteFileName string - balanceFileName string - controlFileName string - invalidVoteTxFileName string - delegateMultiaddressName string - - forgerFileName string - - oldBlockHeight uint64 - oldBlockHash bc.Hash -} - -func newVote(blockHeight uint64, blockHash bc.Hash) (*Vote, error) { - vote := &Vote{ - DelegateVoters: make(map[string]map[string]bool), - VoterDelegates: make(map[string]map[string]bool), - DelegateName: make(map[string]string), - NameDelegate: make(map[string]string), - HashHeightInvalidVote: make(map[bc.Hash]uint64), - AddressBalances: make(map[string]uint64), - DelegateMultiaddress: make(map[string]uint64), - } - - err := vote.New(blockHeight, blockHash) - return vote, err -} - -func (v *Vote) New(blockHeight uint64, blockHash bc.Hash) error { - v.filePath = filepath.Join(config.CommonConfig.RootDir, "dpos") - v.delegateFileName = filepath.Join(v.filePath, DelegateFile) - v.balanceFileName = filepath.Join(v.filePath, BalanceFile) - v.controlFileName = filepath.Join(v.filePath, ControlFile) - v.invalidVoteTxFileName = filepath.Join(v.filePath, InvalidVoteTxFile) - v.delegateMultiaddressName = filepath.Join(v.filePath, DelegateMultiAddressFile) - v.forgerFileName = filepath.Join(v.filePath, ForgerFile) - if blockHeight == 0 { - if err := cmn.EnsureDir(v.filePath, 0700); err != nil { - return err - } - } else { - if err := v.load(blockHeight, blockHash); err != nil { - return err - } - } - return nil -} - -func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool { - v.lockRegister.Lock() - defer v.lockRegister.Unlock() - - if _, ok := v.DelegateName[delegateAddress]; ok { - v.AddInvalidVote(hash, height) - return false - } - if _, ok := v.NameDelegate[delegateName]; ok { - v.AddInvalidVote(hash, height) - return false - } - v.DelegateName[delegateAddress] = delegateName - v.NameDelegate[delegateName] = delegateAddress - return true -} - -func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - votes := 0 - - if delegates, ok := v.VoterDelegates[voterAddress]; ok { - votes = len(delegates) - } - - if votes+len(delegates) > consensus.MaxNumberOfVotes { - v.AddInvalidVote(hash, height) - return false - } - - for _, delegate := range delegates { - if _, ok := v.DelegateName[delegate]; !ok { - v.AddInvalidVote(hash, height) - return false - } - if voters, ok := v.DelegateVoters[delegate]; ok { - if _, ok = voters[voterAddress]; ok { - v.AddInvalidVote(hash, height) - return false - } else { - voters[voterAddress] = true - v.DelegateVoters[delegate] = voters - } - } else { - voters := make(map[string]bool) - voters[voterAddress] = true - v.DelegateVoters[delegate] = voters - } - if dg, ok := v.VoterDelegates[voterAddress]; ok { - dg[delegate] = true - v.VoterDelegates[voterAddress] = dg - } else { - dg := make(map[string]bool) - dg[delegate] = true - v.VoterDelegates[voterAddress] = dg - } - } - return true -} - -func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - for _, delegate := range delegates { - if voters, ok := v.DelegateVoters[delegate]; ok { - if _, ok = voters[voterAddress]; !ok { - v.AddInvalidVote(hash, height) - return false - } else { - if len(voters) == 1 { - delete(v.DelegateVoters, delegate) - } else { - delete(v.DelegateVoters[delegate], voterAddress) - } - } - } else { - v.AddInvalidVote(hash, height) - return false - } - } - - if item, ok := v.VoterDelegates[voterAddress]; ok { - for _, delegate := range delegates { - delete(v.VoterDelegates[voterAddress], delegate) - } - if len(item) == 0 { - delete(v.VoterDelegates, voterAddress) - } - } - - return true -} - -func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error { - if err := v.repairFile(blockHeight, blockHash); err != nil { - return err - } - return v.read() -} - -func (v *Vote) Delete(blockHash bc.Hash) { - os.Remove(v.delegateFileName + "-" + blockHash.String()) - os.Remove(v.voteFileName + "-" + blockHash.String()) - os.Remove(v.balanceFileName + "-" + blockHash.String()) -} - -func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error { - if blockHeight == 0 { - return nil - } - if err := v.Write(blockHash); err != nil { - return err - } - - if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil { - v.Delete(blockHash) - return err - } - - var ( - blockHeightTemp uint64 - blockHashTemp bc.Hash - ) - - if err := v.ReadControlFile(&blockHeightTemp, &blockHashTemp, v.controlFileName); err != nil { - os.Rename(v.controlFileName, v.controlFileName+"-old") - os.Rename(v.controlFileName+"-temp", v.controlFileName) - os.Remove(v.controlFileName + "-old") - } else { - v.Delete(blockHashTemp) - } - - return nil -} - -type forger struct { - DelegateVoters map[string]map[string]bool `json:"delegate_voters"` - VoterDelegates map[string]map[string]bool `json:"voter_delegates"` - DelegateName map[string]string `json:"delegate_name"` - NameDelegate map[string]string `json:"name_delegate"` - HashHeightInvalidVote map[bc.Hash]uint64 `json:"hash_height_invalid_vote"` - AddressBalances map[string]uint64 `json:"address_balance"` - DelegateMultiaddress map[string]uint64 `json:"delegate_multiaddress"` -} - -func (v *Vote) Write(blockHash bc.Hash) error { - - f := forger{ - DelegateVoters: v.DelegateVoters, - VoterDelegates: v.VoterDelegates, - DelegateName: v.DelegateName, - NameDelegate: v.NameDelegate, - HashHeightInvalidVote: v.HashHeightInvalidVote, - AddressBalances: v.AddressBalances, - DelegateMultiaddress: v.DelegateMultiaddress, - } - fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - defer fileObj.Close() - - var data []byte - - if data, err = json.Marshal(&f); err != nil { - return err - } - - if _, err = fileObj.Write(data); err != nil { - return err - } - - return nil -} - -func (v *Vote) read() error { - - if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil { - return err - } - - data, err := ioutil.ReadFile(v.forgerFileName + "-" + v.oldBlockHash.String()) - if err != nil { - return err - } - - f := &forger{} - - if err = json.Unmarshal(data, f); err != nil { - return err - } - - v.DelegateVoters = f.DelegateVoters - v.VoterDelegates = f.VoterDelegates - v.DelegateName = f.DelegateName - v.NameDelegate = f.NameDelegate - v.HashHeightInvalidVote = f.HashHeightInvalidVote - v.AddressBalances = f.AddressBalances - v.DelegateMultiaddress = f.DelegateMultiaddress - - return nil -} - -func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error { - - cmn.EnsureDir(v.filePath, 0700) - - fileName := v.controlFileName + "-temp" - - var ( - blockHeightTmp uint64 - blockHashTmp bc.Hash - ) - - if cmn.FileExists(fileName) { - if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil { - return err - } - if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) { - os.Rename(fileName, v.controlFileName) - return nil - } - os.Remove(fileName) - } - - fileName = v.controlFileName + "-old" - - if cmn.FileExists(fileName) { - if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil { - return err - } - if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) { - os.Rename(fileName, v.controlFileName) - return nil - } - os.Remove(fileName) - } - - fileName = v.controlFileName - if cmn.FileExists(fileName) { - if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil { - return err - } - if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) { - return nil - } - } - - return fmt.Errorf("repairFile fail in %d height", blockHeightTmp) -} - -func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - var result []Delegate - for k, value := range v.DelegateVoters { - votes := uint64(0) - for address := range value { - votes += v.GetAddressBalance(address) - } - if v.GetAddressBalance(k) >= minHoldBalance { - result = append(result, Delegate{k, votes}) - } - } - sort.Sort(DelegateWrapper{result, func(p, q *Delegate) bool { - if p.Votes < q.Votes { - return false - } else if p.Votes > q.Votes { - return true - } - return bytes.Compare([]byte(p.DelegateAddress), []byte(q.DelegateAddress)) > 0 - }}) - - for k := range v.DelegateName { - if uint64(len(result)) >= delegateNum { - break - } - if v.GetAddressBalance(k) < consensus.MinHoldBalance { - continue - } - if _, ok := v.DelegateVoters[k]; !ok { - result = append(result, Delegate{k, 0}) - } - } - if uint64(len(result)) <= delegateNum { - return result - } - result = result[:delegateNum] - return result -} - -func (v *Vote) GetAddressBalance(address string) uint64 { - - if votes, ok := v.AddressBalances[address]; ok { - return votes - } - - return 0 -} - -type control struct { - BlockHeight uint64 `json:"block_height"` - BlockHash bc.Hash `json:"block_hash"` -} - -func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error { - data, err := ioutil.ReadFile(fileName) - if err != nil { - return err - } - c := &control{} - - if err = json.Unmarshal(data, c); err != nil { - return err - } - - *blockHash = c.BlockHash - *blockHeight = c.BlockHeight - return nil -} - -func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error { - - fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - defer fileObj.Close() - - c := control{ - BlockHeight: blockHeight, - BlockHash: blockHash, - } - - var data []byte - - if data, err = json.Marshal(&c); err != nil { - return err - } - - if _, err = fileObj.Write(data); err != nil { - return err - } - - return nil -} - -func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - mapBalance := make(map[string]int64) - - for _, value := range addressBalance { - if value.Balance == 0 { - continue - } - mapBalance[value.Address] += value.Balance - } - for addr, balance := range mapBalance { - v.updateAddressBalance(addr, balance) - } -} - -func (v *Vote) updateAddressBalance(address string, value int64) { - if val, ok := v.AddressBalances[address]; ok { - banlance := int64(val) + value - if banlance < 0 { - cmn.Exit(fmt.Sprintf("The balance was negative: %s: %d", address, value)) - } - if banlance == 0 { - delete(v.AddressBalances, address) - } else { - v.AddressBalances[address] = uint64(banlance) - } - } else { - if value < 0 { - cmn.Exit(fmt.Sprintf("The balance was negative: %s: %d", address, value)) - } - if value > 0 { - v.AddressBalances[address] = uint64(value) - } - } -} - -func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) { - v.lockHashHeightInvalidVote.Lock() - defer v.lockHashHeightInvalidVote.Unlock() - v.HashHeightInvalidVote[hash] = height -} -func (v *Vote) DeleteInvalidVote(height uint64) { - v.lockHashHeightInvalidVote.Lock() - defer v.lockHashHeightInvalidVote.Unlock() - for k, value := range v.HashHeightInvalidVote { - if value <= height { - delete(v.HashHeightInvalidVote, k) - } - } -} - -func (v *Vote) GetOldBlockHeight() uint64 { - return v.oldBlockHeight -} - -func (v *Vote) GetOldBlockHash() bc.Hash { - return v.oldBlockHash -} - -func (v *Vote) GetDelegate(name string) string { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - if delegate, ok := v.NameDelegate[name]; ok { - return delegate - } - return "" -} - -func (v *Vote) GetDelegateName(address string) string { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - if name, ok := v.DelegateName[address]; ok { - return name - } - return "" -} - -func (v *Vote) HaveVote(voter string, delegate string) bool { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - if voters, ok := v.DelegateVoters[delegate]; ok { - if _, ok := voters[voter]; ok { - return true - } - } - - return false -} - -func (v *Vote) HaveDelegate(name string, delegate string) bool { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - if n, ok := v.DelegateName[delegate]; ok { - if n == name { - return true - } - } - - return false -} - -func (v *Vote) GetVotedDelegates(voter string) []string { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - var results []string - if delegates, ok := v.VoterDelegates[voter]; ok { - for delegate, _ := range delegates { - results = append(results, delegate) - } - } - return results -} - -func (v *Vote) ListDelegates() map[string]string { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - return v.NameDelegate -} - -func (v *Vote) GetDelegateVotes(delegate string) uint64 { - votes := uint64(0) - if voters, ok := v.DelegateVoters[delegate]; ok { - for voter := range voters { - votes += v.GetAddressBalance(voter) - } - } - return votes -} - -func (v *Vote) GetDelegateVoters(delegate string) []string { - v.lockVoter.Lock() - defer v.lockVoter.Unlock() - - var result []string - - if voters, ok := v.DelegateVoters[delegate]; ok { - for voter := range voters { - result = append(result, voter) - } - } - - return result -}