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  }