|
|
- package state
-
- import (
- "fmt"
- "io"
- "strings"
-
- . "github.com/tendermint/tendermint/binary"
- "github.com/tendermint/tendermint/merkle"
- )
-
- // Not goroutine-safe.
- // TODO: consider validator Accum overflow?
- type ValidatorSet struct {
- validators merkle.Tree
- proposer *Validator // Whoever has the highest Accum.
- totalVotingPower uint64
- }
-
- func NewValidatorSet(vals []*Validator) *ValidatorSet {
- validators := merkle.NewIAVLTree(BasicCodec, ValidatorCodec, 0, nil) // In memory
- var proposer *Validator
- totalVotingPower := uint64(0)
- for _, val := range vals {
- validators.Set(val.Id, val)
- proposer = proposer.CompareAccum(val)
- totalVotingPower += val.VotingPower
- }
- return &ValidatorSet{
- validators: validators,
- proposer: proposer,
- totalVotingPower: totalVotingPower,
- }
- }
-
- func ReadValidatorSet(r io.Reader, n *int64, err *error) *ValidatorSet {
- size := ReadUInt64(r, n, err)
- validators := []*Validator{}
- for i := uint64(0); i < size; i++ {
- validator := ReadValidator(r, n, err)
- validators = append(validators, validator)
- }
- return NewValidatorSet(validators)
- }
-
- func (vset *ValidatorSet) WriteTo(w io.Writer) (n int64, err error) {
- WriteUInt64(w, uint64(vset.validators.Size()), &n, &err)
- vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
- val := val_.(*Validator)
- WriteBinary(w, val, &n, &err)
- return false
- })
- return
- }
-
- func (vset *ValidatorSet) IncrementAccum() {
- // Decrement from previous proposer
- vset.proposer.Accum -= int64(vset.totalVotingPower)
- var proposer *Validator
- // Increment accum and find proposer
- vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
- val := val_.(*Validator)
- val.Accum += int64(val.VotingPower)
- proposer = proposer.CompareAccum(val)
- return false
- })
- vset.proposer = proposer
- }
-
- func (vset *ValidatorSet) Copy() *ValidatorSet {
- return &ValidatorSet{
- validators: vset.validators.Copy(),
- proposer: vset.proposer,
- totalVotingPower: vset.totalVotingPower,
- }
- }
-
- func (vset *ValidatorSet) GetById(id uint64) (index uint32, val *Validator) {
- index_, val_ := vset.validators.Get(id)
- index, val = uint32(index_), val_.(*Validator)
- return
- }
-
- func (vset *ValidatorSet) HasId(id uint64) bool {
- _, val_ := vset.validators.Get(id)
- return val_ != nil
- }
-
- func (vset *ValidatorSet) GetByIndex(index uint32) (id uint64, val *Validator) {
- id_, val_ := vset.validators.GetByIndex(uint64(index))
- id, val = id_.(uint64), val_.(*Validator)
- return
- }
-
- func (vset *ValidatorSet) Size() uint {
- return uint(vset.validators.Size())
- }
-
- func (vset *ValidatorSet) TotalVotingPower() uint64 {
- return vset.totalVotingPower
- }
-
- func (vset *ValidatorSet) Proposer() (proposer *Validator) {
- return vset.proposer
- }
-
- func (vset *ValidatorSet) Hash() []byte {
- return vset.validators.Hash()
- }
-
- func (vset *ValidatorSet) Add(val *Validator) (added bool) {
- if vset.validators.Has(val.Id) {
- return false
- }
- return !vset.validators.Set(val.Id, val)
- }
-
- func (vset *ValidatorSet) Update(val *Validator) (updated bool) {
- if !vset.validators.Has(val.Id) {
- return false
- }
- return vset.validators.Set(val.Id, val)
- }
-
- func (vset *ValidatorSet) Remove(validatorId uint64) (val *Validator, removed bool) {
- val_, removed := vset.validators.Remove(validatorId)
- return val_.(*Validator), removed
- }
-
- func (vset *ValidatorSet) Iterate(fn func(val *Validator) bool) {
- vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
- return fn(val_.(*Validator))
- })
- }
-
- func (vset *ValidatorSet) String() string {
- return vset.StringWithIndent("")
- }
-
- func (vset *ValidatorSet) StringWithIndent(indent string) string {
- valStrings := []string{}
- vset.Iterate(func(val *Validator) bool {
- valStrings = append(valStrings, val.String())
- return false
- })
- return fmt.Sprintf(`ValidatorSet{
- %s Proposer: %v
- %s Validators:
- %s %v
- %s}`,
- indent, vset.proposer.String(),
- indent,
- indent, strings.Join(valStrings, "\n"+indent+" "),
- indent)
-
- }
|