Browse Source

update privValidatorIndex on valset change

pull/319/head
Ethan Buchman 8 years ago
parent
commit
e0db20c0cf
6 changed files with 37 additions and 26 deletions
  1. +0
    -1
      consensus/common_test.go
  2. +17
    -9
      consensus/state.go
  3. +0
    -7
      node/node.go
  4. +13
    -8
      state/execution.go
  5. +6
    -0
      state/state.go
  6. +1
    -1
      types/block.go

+ 0
- 1
consensus/common_test.go View File

@ -262,7 +262,6 @@ func randConsensusNet(nValidators int) []*ConsensusState {
thisConfig := tendermint_test.ResetConfig(Fmt("consensus_reactor_test_%d", i)) thisConfig := tendermint_test.ResetConfig(Fmt("consensus_reactor_test_%d", i))
EnsureDir(thisConfig.GetString("cs_wal_dir"), 0700) // dir for wal EnsureDir(thisConfig.GetString("cs_wal_dir"), 0700) // dir for wal
css[i] = newConsensusStateWithConfig(thisConfig, state, privVals[i], counter.NewCounterApplication(true)) css[i] = newConsensusStateWithConfig(thisConfig, state, privVals[i], counter.NewCounterApplication(true))
css[i].SetPrivValidatorIndex(i)
} }
return css return css
} }


+ 17
- 9
consensus/state.go View File

@ -226,8 +226,8 @@ type ConsensusState struct {
blockStore *bc.BlockStore blockStore *bc.BlockStore
mempool *mempl.Mempool mempool *mempl.Mempool
privValidator PrivValidator
privValidatorIndex int // TODO: update if validator set changes
privValidator PrivValidator // for signing votes
privValidatorIndex int // cached index; updated if validators added/removed to validator set
mtx sync.Mutex mtx sync.Mutex
RoundState RoundState
@ -320,13 +320,7 @@ func (cs *ConsensusState) SetPrivValidator(priv PrivValidator) {
cs.mtx.Lock() cs.mtx.Lock()
defer cs.mtx.Unlock() defer cs.mtx.Unlock()
cs.privValidator = priv cs.privValidator = priv
}
// Caches the index of our privValidator in the validator set to use when voting
func (cs *ConsensusState) SetPrivValidatorIndex(index int) {
cs.mtx.Lock()
defer cs.mtx.Unlock()
cs.privValidatorIndex = index
cs.setPrivValidatorIndex()
} }
func (cs *ConsensusState) LoadCommit(height int) *types.Commit { func (cs *ConsensusState) LoadCommit(height int) *types.Commit {
@ -585,10 +579,24 @@ func (cs *ConsensusState) updateToState(state *sm.State) {
cs.state = state cs.state = state
if cs.state.ValidatorAddedOrRemoved() {
cs.setPrivValidatorIndex()
}
// Finally, broadcast RoundState // Finally, broadcast RoundState
cs.newStep() cs.newStep()
} }
func (cs *ConsensusState) setPrivValidatorIndex() {
// TODO: just return -1 for not found
valIdx, val := cs.state.Validators.GetByAddress(cs.privValidator.GetAddress())
if val == nil {
cs.privValidatorIndex = -1
} else {
cs.privValidatorIndex = valIdx
}
}
func (cs *ConsensusState) newStep() { func (cs *ConsensusState) newStep() {
rs := cs.RoundStateEvent() rs := cs.RoundStateEvent()
cs.wal.Save(rs) cs.wal.Save(rs)


+ 0
- 7
node/node.go View File

@ -103,13 +103,6 @@ func NewNode(config cfg.Config, privValidator *types.PrivValidator, clientCreato
consensusState := consensus.NewConsensusState(config, state.Copy(), proxyApp.Consensus(), blockStore, mempool) consensusState := consensus.NewConsensusState(config, state.Copy(), proxyApp.Consensus(), blockStore, mempool)
if privValidator != nil { if privValidator != nil {
consensusState.SetPrivValidator(privValidator) consensusState.SetPrivValidator(privValidator)
// TODO: just return -1 for not found
valIdx, val := state.Validators.GetByAddress(privValidator.GetAddress())
if val == nil {
consensusState.SetPrivValidatorIndex(-1)
} else {
consensusState.SetPrivValidatorIndex(valIdx)
}
} }
consensusReactor := consensus.NewConsensusReactor(consensusState, fastSync) consensusReactor := consensus.NewConsensusReactor(consensusState, fastSync)


+ 13
- 8
state/execution.go View File

@ -43,7 +43,8 @@ func (s *State) ExecBlock(eventCache types.Fireable, proxyAppConn proxy.AppConnC
} }
// update the validator set // update the validator set
if err := updateValidators(nextValSet, changedValidators); err != nil {
s.valAddedOrRemoved, err = updateValidators(nextValSet, changedValidators)
if err != nil {
log.Warn("Error changing validator set", "error", err) log.Warn("Error changing validator set", "error", err)
// TODO: err or carry on? // TODO: err or carry on?
} }
@ -131,20 +132,22 @@ func execBlockOnProxyApp(eventCache types.Fireable, proxyAppConn proxy.AppConnCo
return changedValidators, nil return changedValidators, nil
} }
func updateValidators(validators *types.ValidatorSet, changedValidators []*tmsp.Validator) error {
func updateValidators(validators *types.ValidatorSet, changedValidators []*tmsp.Validator) (bool, error) {
// TODO: prevent change of 1/3+ at once // TODO: prevent change of 1/3+ at once
var addedOrRemoved bool
for _, v := range changedValidators { for _, v := range changedValidators {
pubkey, err := crypto.PubKeyFromBytes(v.PubKey) // NOTE: expects go-wire encoded pubkey pubkey, err := crypto.PubKeyFromBytes(v.PubKey) // NOTE: expects go-wire encoded pubkey
if err != nil { if err != nil {
return err
return false, err
} }
address := pubkey.Address() address := pubkey.Address()
power := int64(v.Power) power := int64(v.Power)
// mind the overflow from uint64 // mind the overflow from uint64
if power < 0 { if power < 0 {
return errors.New(Fmt("Power (%d) overflows int64", v.Power))
return false, errors.New(Fmt("Power (%d) overflows int64", v.Power))
} }
_, val := validators.GetByAddress(address) _, val := validators.GetByAddress(address)
@ -152,24 +155,26 @@ func updateValidators(validators *types.ValidatorSet, changedValidators []*tmsp.
// add val // add val
added := validators.Add(types.NewValidator(pubkey, power)) added := validators.Add(types.NewValidator(pubkey, power))
if !added { if !added {
return errors.New(Fmt("Failed to add new validator %X with voting power %d", address, power))
return false, errors.New(Fmt("Failed to add new validator %X with voting power %d", address, power))
} }
addedOrRemoved = true
} else if v.Power == 0 { } else if v.Power == 0 {
// remove val // remove val
_, removed := validators.Remove(address) _, removed := validators.Remove(address)
if !removed { if !removed {
return errors.New(Fmt("Failed to remove validator %X)"))
return false, errors.New(Fmt("Failed to remove validator %X)"))
} }
addedOrRemoved = true
} else { } else {
// update val // update val
val.VotingPower = power val.VotingPower = power
updated := validators.Update(val) updated := validators.Update(val)
if !updated { if !updated {
return errors.New(Fmt("Failed to update validator %X with voting power %d", address, power))
return false, errors.New(Fmt("Failed to update validator %X with voting power %d", address, power))
} }
} }
} }
return nil
return addedOrRemoved, nil
} }
// return a bit array of validators that signed the last commit // return a bit array of validators that signed the last commit


+ 6
- 0
state/state.go View File

@ -40,6 +40,8 @@ type State struct {
// it's stale after ExecBlock and before Commit // it's stale after ExecBlock and before Commit
Stale bool Stale bool
AppHash []byte AppHash []byte
valAddedOrRemoved bool // true if a validator was added or removed
} }
func LoadState(db dbm.DB) *State { func LoadState(db dbm.DB) *State {
@ -105,6 +107,10 @@ func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader typ
s.Stale = true s.Stale = true
} }
func (s *State) ValidatorAddedOrRemoved() bool {
return s.valAddedOrRemoved
}
func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) { func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
return s.LastValidators, s.Validators return s.LastValidators, s.Validators
} }


+ 1
- 1
types/block.go View File

@ -155,8 +155,8 @@ type Header struct {
NumTxs int `json:"num_txs"` NumTxs int `json:"num_txs"`
LastBlockID BlockID `json:"last_block_id"` LastBlockID BlockID `json:"last_block_id"`
LastCommitHash []byte `json:"last_commit_hash"` // commit from validators from the last block LastCommitHash []byte `json:"last_commit_hash"` // commit from validators from the last block
ValidatorsHash []byte `json:"validators_hash"` // validators for the current block
DataHash []byte `json:"data_hash"` // transactions DataHash []byte `json:"data_hash"` // transactions
ValidatorsHash []byte `json:"validators_hash"` // validators for the current block
AppHash []byte `json:"app_hash"` // state after txs from the previous block AppHash []byte `json:"app_hash"` // state after txs from the previous block
} }


Loading…
Cancel
Save