OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / consensus / consensus / dpos / vote.go
diff --git a/consensus/consensus/dpos/vote.go b/consensus/consensus/dpos/vote.go
deleted file mode 100644 (file)
index 405d235..0000000
+++ /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
-}