github.com/Gessiux/neatchain@v1.3.1/chain/consensus/neatcon/epoch/epoch_vote.go (about) 1 package epoch 2 3 import ( 4 "fmt" 5 "math/big" 6 "sync" 7 8 "github.com/Gessiux/go-crypto" 9 "github.com/Gessiux/go-db" 10 "github.com/Gessiux/go-wire" 11 "github.com/Gessiux/neatchain/chain/log" 12 "github.com/Gessiux/neatchain/utilities/common" 13 ) 14 15 var voteRWMutex sync.RWMutex 16 17 // Epoch Validator Vote Set 18 // Store in the Level DB will be Key + EpochValidatorVoteSet 19 // Key = string EpochValidatorVoteKey 20 // Value = []byte EpochValidatorVoteSet 21 // eg. Key: EpochValidatorVote_1, EpochValidatorVote_2 22 func calcEpochValidatorVoteKey(epochNumber uint64) []byte { 23 return []byte(fmt.Sprintf("EpochValidatorVote_%v", epochNumber)) 24 } 25 26 type EpochValidatorVoteSet struct { 27 // Store the Votes 28 Votes []*EpochValidatorVote 29 // For fast searching, key = Address Hex (not export) 30 votesByAddress map[common.Address]*EpochValidatorVote 31 } 32 33 type EpochValidatorVote struct { 34 Address common.Address 35 PubKey crypto.PubKey 36 Amount *big.Int 37 Salt string 38 VoteHash common.Hash // VoteHash = Sha3(Address + PubKey + Amount + Salt) 39 TxHash common.Hash 40 } 41 42 func NewEpochValidatorVoteSet() *EpochValidatorVoteSet { 43 return &EpochValidatorVoteSet{ 44 Votes: make([]*EpochValidatorVote, 0), 45 votesByAddress: make(map[common.Address]*EpochValidatorVote), 46 } 47 } 48 49 // GetVoteByAddress get the Vote from VoteSet by Address Hex Key 50 func (voteSet *EpochValidatorVoteSet) GetVoteByAddress(address common.Address) (vote *EpochValidatorVote, exist bool) { 51 voteRWMutex.RLock() 52 defer voteRWMutex.RUnlock() 53 54 vote, exist = voteSet.votesByAddress[address] 55 return 56 } 57 58 // StoreVote insert or update the Vote into VoteSet by Address Hex Key 59 func (voteSet *EpochValidatorVoteSet) StoreVote(vote *EpochValidatorVote) { 60 voteRWMutex.Lock() 61 defer voteRWMutex.Unlock() 62 63 oldVote, exist := voteSet.votesByAddress[vote.Address] 64 if exist { 65 // Exist, remove it 66 index := -1 67 for i := 0; i < len(voteSet.Votes); i++ { 68 if voteSet.Votes[i] == oldVote { 69 index = i 70 break 71 } 72 } 73 voteSet.Votes = append(voteSet.Votes[:index], voteSet.Votes[index+1:]...) 74 } 75 voteSet.votesByAddress[vote.Address] = vote 76 voteSet.Votes = append(voteSet.Votes, vote) 77 } 78 79 func SaveEpochVoteSet(epochDB db.DB, epochNumber uint64, voteSet *EpochValidatorVoteSet) { 80 voteRWMutex.Lock() 81 defer voteRWMutex.Unlock() 82 83 epochDB.SetSync(calcEpochValidatorVoteKey(epochNumber), wire.BinaryBytes(*voteSet)) 84 } 85 86 func LoadEpochVoteSet(epochDB db.DB, epochNumber uint64) *EpochValidatorVoteSet { 87 voteRWMutex.RLock() 88 defer voteRWMutex.RUnlock() 89 90 data := epochDB.Get(calcEpochValidatorVoteKey(epochNumber)) 91 if len(data) == 0 { 92 return nil 93 } else { 94 var voteSet EpochValidatorVoteSet 95 err := wire.ReadBinaryBytes(data, &voteSet) 96 if err != nil { 97 log.Error("Load Epoch Vote Set failed", "error", err) 98 return nil 99 } 100 // Fulfill the Vote Map 101 voteSet.votesByAddress = make(map[common.Address]*EpochValidatorVote) 102 for _, v := range voteSet.Votes { 103 voteSet.votesByAddress[v.Address] = v 104 } 105 return &voteSet 106 } 107 } 108 109 func (voteSet *EpochValidatorVoteSet) Copy() *EpochValidatorVoteSet { 110 if voteSet == nil { 111 return nil 112 } 113 114 votes_copy := make([]*EpochValidatorVote, 0, len(voteSet.Votes)) 115 votesByAddress_copy := make(map[common.Address]*EpochValidatorVote, len(voteSet.Votes)) 116 for _, vote := range voteSet.Votes { 117 v := vote.Copy() 118 votes_copy = append(votes_copy, v) 119 votesByAddress_copy[vote.Address] = v 120 } 121 122 return &EpochValidatorVoteSet{ 123 Votes: votes_copy, 124 votesByAddress: votesByAddress_copy, 125 } 126 } 127 128 func (voteSet *EpochValidatorVoteSet) IsEmpty() bool { 129 return voteSet == nil || len(voteSet.Votes) == 0 130 } 131 132 func (vote *EpochValidatorVote) Copy() *EpochValidatorVote { 133 vCopy := *vote 134 return &vCopy 135 }