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