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  }