9 "github.com/vapor/config"
11 "github.com/vapor/consensus"
12 "github.com/vapor/protocol/bc"
17 DelegateFile = "delegate.dat"
18 BalanceFile = "balance.dat"
19 ControlFile = "control.dat"
20 InvalidVoteTxFile = "invalidvotetx.dat"
21 DelegateMultiAddressFile = "delegatemultiaddress.dat"
23 ForgerFile = "forger.data"
26 type AddressBalance struct {
32 DelegateVoters map[string]map[string]bool
33 VoterDelegates map[string]map[string]bool
35 DelegateName map[string]string
36 NameDelegate map[string]string
37 lockRegister sync.Mutex
38 HashHeightInvalidVote map[bc.Hash]uint64
39 lockHashHeightInvalidVote sync.Mutex
40 AddressBalances map[string]uint64
41 DelegateMultiaddress map[string]uint64
44 delegateFileName string
46 balanceFileName string
47 controlFileName string
48 invalidVoteTxFileName string
49 delegateMultiaddressName string
59 func (v *Vote) new(blockHeight uint64, blockHash bc.Hash) error {
61 v.filePath = filepath.Join(config.DefaultDataDir(), "dpos")
62 v.delegateFileName = filepath.Join(v.filePath, DelegateFile)
63 v.balanceFileName = filepath.Join(v.filePath, BalanceFile)
64 v.controlFileName = filepath.Join(v.filePath, ControlFile)
65 v.invalidVoteTxFileName = filepath.Join(v.filePath, InvalidVoteTxFile)
66 v.delegateMultiaddressName = filepath.Join(v.filePath, DelegateMultiAddressFile)
67 v.forgerFileName = filepath.Join(v.filePath, ForgerFile)
69 if _, err := os.Stat(v.filePath); os.IsNotExist(err) {
70 err := os.MkdirAll(v.filePath, 0700)
72 //return fmt.Errorf("Could not create directory %v. %v", dir, err)
77 if err := v.load(blockHeight, blockHash); err != nil {
84 func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
86 defer v.lockRegister.Unlock()
87 if _, ok := v.DelegateName[delegateAddress]; !ok {
88 v.AddInvalidVote(hash, height)
92 if _, ok := v.NameDelegate[delegateName]; !ok {
93 v.AddInvalidVote(hash, height)
97 v.DelegateName[delegateAddress] = delegateName
98 v.NameDelegate[delegateName] = delegateAddress
102 func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
104 defer v.lockVoter.Unlock()
108 if delegates, ok := v.VoterDelegates[voterAddress]; ok {
109 votes = len(delegates)
112 if votes+len(delegates) > consensus.MaxNumberOfVotes {
113 v.AddInvalidVote(hash, height)
117 for _, delegate := range delegates {
118 if _, ok := v.DelegateName[delegate]; !ok {
119 v.AddInvalidVote(hash, height)
122 if voters, ok := v.DelegateVoters[delegate]; ok {
123 if _, ok = voters[voterAddress]; ok {
124 v.AddInvalidVote(hash, height)
127 v.DelegateVoters[delegate][voterAddress] = true
130 v.DelegateVoters[delegate][voterAddress] = true
132 v.VoterDelegates[voterAddress][delegate] = true
138 func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
140 defer v.lockVoter.Unlock()
142 for _, delegate := range delegates {
143 if voters, ok := v.DelegateVoters[delegate]; ok {
144 if _, ok = voters[voterAddress]; !ok {
145 v.AddInvalidVote(hash, height)
148 if len(voters) == 1 {
149 delete(v.DelegateVoters, delegate)
151 delete(v.DelegateVoters[delegate], voterAddress)
155 v.AddInvalidVote(hash, height)
160 if item, ok := v.VoterDelegates[voterAddress]; ok {
161 for _, delegate := range delegates {
162 delete(v.VoterDelegates[voterAddress], delegate)
165 delete(v.VoterDelegates, voterAddress)
172 func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
173 v.lockHashHeightInvalidVote.Lock()
174 defer v.lockHashHeightInvalidVote.Unlock()
175 v.HashHeightInvalidVote[hash] = height
178 func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error {
179 if err := v.repairFile(blockHeight, blockHash); err != nil {
185 func (v *Vote) Delete(blockHash bc.Hash) {
186 os.Remove(v.delegateFileName + "-" + blockHash.String())
187 os.Remove(v.voteFileName + "-" + blockHash.String())
188 os.Remove(v.balanceFileName + "-" + blockHash.String())
191 func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
192 if blockHeight == 0 {
195 if err := v.Write(blockHash); err != nil {
199 if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil {
204 blockHeightTemp uint64
205 blockHashTemp bc.Hash
208 if err := v.ReadControlFile(&blockHeightTemp, &blockHashTemp, v.controlFileName); err != nil {
212 os.Rename(v.controlFileName, v.controlFileName+"-old")
213 os.Rename(v.controlFileName+"-temp", v.controlFileName)
214 os.Remove(v.controlFileName + "-old")
220 DelegateVoters map[string]map[string]bool `json:"delegate_voters"`
221 VoterDelegates map[string]map[string]bool `json:"voter_delegates"`
222 DelegateName map[string]string `json:"delegate_name"`
223 NameDelegate map[string]string `json:"name_delegate"`
224 HashHeightInvalidVote map[bc.Hash]uint64 `json:"hash_height_invalid_vote"`
225 AddressBalances map[string]uint64 `json:"address_balance"`
226 DelegateMultiaddress map[string]uint64 `json:"delegate_multiaddress"`
229 func (v *Vote) Write(blockHash bc.Hash) error {
232 DelegateVoters: v.DelegateVoters,
233 VoterDelegates: v.VoterDelegates,
234 DelegateName: v.DelegateName,
235 NameDelegate: v.NameDelegate,
236 HashHeightInvalidVote: v.HashHeightInvalidVote,
237 AddressBalances: v.AddressBalances,
238 DelegateMultiaddress: v.DelegateMultiaddress,
241 fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
245 defer fileObj.Close()
249 if data, err = json.Marshal(&f); err != nil {
253 if _, err = fileObj.Write(data); err != nil {
260 func (v *Vote) read() error {
262 if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil {
266 fileObj, err := os.OpenFile(v.forgerFileName+"-"+v.oldBlockHash.String(), os.O_RDONLY, 0644)
273 if _, err = fileObj.Read(data); err != nil {
279 if err = json.Unmarshal(data, f); err != nil {
283 v.DelegateVoters = f.DelegateVoters
284 v.VoterDelegates = f.VoterDelegates
285 v.DelegateName = f.DelegateName
286 v.NameDelegate = f.NameDelegate
287 v.HashHeightInvalidVote = f.HashHeightInvalidVote
288 v.AddressBalances = f.AddressBalances
289 v.DelegateMultiaddress = f.DelegateMultiaddress
294 func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error {
298 func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate {
299 var result []Delegate
304 type control struct {
305 BlockHeight uint64 `json:"block_height"`
306 BlockHash bc.Hash `json:"block_hash"`
309 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
311 fileObj, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
318 if _, err = fileObj.Read(data); err != nil {
324 if err = json.Unmarshal(data, c); err != nil {
328 *blockHash = c.BlockHash
329 *blockHeight = c.BlockHeight
333 func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error {
335 fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
339 defer fileObj.Close()
342 BlockHeight: blockHeight,
343 BlockHash: blockHash,
348 if data, err = json.Marshal(&c); err != nil {
352 if _, err = fileObj.Write(data); err != nil {
359 func (v *Vote) UpdateAddressBalance(AddressBalance []AddressBalance) {