mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-26 15:22:15 +00:00
Validation validation bug fix --> keep track of LastBondedValidators
This commit is contained in:
parent
b3b6a24317
commit
d1a36d2ac2
@ -71,8 +71,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
roundDuration0 = 60 * time.Second // The first round is 60 seconds long.
|
roundDuration0 = 30 * time.Second // The first round is 60 seconds long.
|
||||||
roundDurationDelta = 15 * time.Second // Each successive round lasts 15 seconds longer.
|
roundDurationDelta = 10 * time.Second // Each successive round lasts 15 seconds longer.
|
||||||
roundDeadlinePrevote = float64(1.0 / 3.0) // When the prevote is due.
|
roundDeadlinePrevote = float64(1.0 / 3.0) // When the prevote is due.
|
||||||
roundDeadlinePrecommit = float64(2.0 / 3.0) // When the precommit vote is due.
|
roundDeadlinePrecommit = float64(2.0 / 3.0) // When the precommit vote is due.
|
||||||
newHeightDelta = roundDuration0 / 3 // The time to wait between commitTime and startTime of next consensus rounds.
|
newHeightDelta = roundDuration0 / 3 // The time to wait between commitTime and startTime of next consensus rounds.
|
||||||
|
@ -110,6 +110,7 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
|
|||||||
LastBlockParts: blk.PartSetHeader{},
|
LastBlockParts: blk.PartSetHeader{},
|
||||||
LastBlockTime: genDoc.GenesisTime,
|
LastBlockTime: genDoc.GenesisTime,
|
||||||
BondedValidators: NewValidatorSet(validators),
|
BondedValidators: NewValidatorSet(validators),
|
||||||
|
LastBondedValidators: NewValidatorSet(nil),
|
||||||
UnbondingValidators: NewValidatorSet(nil),
|
UnbondingValidators: NewValidatorSet(nil),
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
validatorInfos: validatorInfos,
|
validatorInfos: validatorInfos,
|
||||||
|
@ -43,6 +43,7 @@ type State struct {
|
|||||||
LastBlockParts blk.PartSetHeader
|
LastBlockParts blk.PartSetHeader
|
||||||
LastBlockTime time.Time
|
LastBlockTime time.Time
|
||||||
BondedValidators *ValidatorSet
|
BondedValidators *ValidatorSet
|
||||||
|
LastBondedValidators *ValidatorSet
|
||||||
UnbondingValidators *ValidatorSet
|
UnbondingValidators *ValidatorSet
|
||||||
accounts merkle.Tree // Shouldn't be accessed directly.
|
accounts merkle.Tree // Shouldn't be accessed directly.
|
||||||
validatorInfos merkle.Tree // Shouldn't be accessed directly.
|
validatorInfos merkle.Tree // Shouldn't be accessed directly.
|
||||||
@ -60,6 +61,7 @@ func LoadState(db dbm.DB) *State {
|
|||||||
s.LastBlockParts = binary.ReadBinary(blk.PartSetHeader{}, r, n, err).(blk.PartSetHeader)
|
s.LastBlockParts = binary.ReadBinary(blk.PartSetHeader{}, r, n, err).(blk.PartSetHeader)
|
||||||
s.LastBlockTime = binary.ReadTime(r, n, err)
|
s.LastBlockTime = binary.ReadTime(r, n, err)
|
||||||
s.BondedValidators = binary.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
s.BondedValidators = binary.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
||||||
|
s.LastBondedValidators = binary.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
||||||
s.UnbondingValidators = binary.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
s.UnbondingValidators = binary.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
||||||
accountsHash := binary.ReadByteSlice(r, n, err)
|
accountsHash := binary.ReadByteSlice(r, n, err)
|
||||||
s.accounts = merkle.NewIAVLTree(binary.BasicCodec, account.AccountCodec, defaultAccountsCacheCapacity, db)
|
s.accounts = merkle.NewIAVLTree(binary.BasicCodec, account.AccountCodec, defaultAccountsCacheCapacity, db)
|
||||||
@ -85,6 +87,7 @@ func (s *State) Save() {
|
|||||||
binary.WriteBinary(s.LastBlockParts, buf, n, err)
|
binary.WriteBinary(s.LastBlockParts, buf, n, err)
|
||||||
binary.WriteTime(s.LastBlockTime, buf, n, err)
|
binary.WriteTime(s.LastBlockTime, buf, n, err)
|
||||||
binary.WriteBinary(s.BondedValidators, buf, n, err)
|
binary.WriteBinary(s.BondedValidators, buf, n, err)
|
||||||
|
binary.WriteBinary(s.LastBondedValidators, buf, n, err)
|
||||||
binary.WriteBinary(s.UnbondingValidators, buf, n, err)
|
binary.WriteBinary(s.UnbondingValidators, buf, n, err)
|
||||||
binary.WriteByteSlice(s.accounts.Hash(), buf, n, err)
|
binary.WriteByteSlice(s.accounts.Hash(), buf, n, err)
|
||||||
binary.WriteByteSlice(s.validatorInfos.Hash(), buf, n, err)
|
binary.WriteByteSlice(s.validatorInfos.Hash(), buf, n, err)
|
||||||
@ -102,6 +105,7 @@ func (s *State) Copy() *State {
|
|||||||
LastBlockParts: s.LastBlockParts,
|
LastBlockParts: s.LastBlockParts,
|
||||||
LastBlockTime: s.LastBlockTime,
|
LastBlockTime: s.LastBlockTime,
|
||||||
BondedValidators: s.BondedValidators.Copy(),
|
BondedValidators: s.BondedValidators.Copy(),
|
||||||
|
LastBondedValidators: s.LastBondedValidators.Copy(),
|
||||||
UnbondingValidators: s.UnbondingValidators.Copy(),
|
UnbondingValidators: s.UnbondingValidators.Copy(),
|
||||||
accounts: s.accounts.Copy(),
|
accounts: s.accounts.Copy(),
|
||||||
validatorInfos: s.validatorInfos.Copy(),
|
validatorInfos: s.validatorInfos.Copy(),
|
||||||
@ -352,7 +356,7 @@ func (s *State) ExecTx(tx_ blk.Tx) error {
|
|||||||
|
|
||||||
// tx.Height must be equal to the next height
|
// tx.Height must be equal to the next height
|
||||||
if tx.Height != s.LastBlockHeight+1 {
|
if tx.Height != s.LastBlockHeight+1 {
|
||||||
return errors.New("Invalid rebond height")
|
return errors.New(Fmt("Invalid rebond height. Expected %v, got %v", s.LastBlockHeight+1, tx.Height))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good!
|
// Good!
|
||||||
@ -364,6 +368,12 @@ func (s *State) ExecTx(tx_ blk.Tx) error {
|
|||||||
|
|
||||||
// Verify the signatures
|
// Verify the signatures
|
||||||
_, accused := s.BondedValidators.GetByAddress(tx.Address)
|
_, accused := s.BondedValidators.GetByAddress(tx.Address)
|
||||||
|
if accused == nil {
|
||||||
|
_, accused = s.UnbondingValidators.GetByAddress(tx.Address)
|
||||||
|
if accused == nil {
|
||||||
|
return blk.ErrTxInvalidAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
voteASignBytes := account.SignBytes(&tx.VoteA)
|
voteASignBytes := account.SignBytes(&tx.VoteA)
|
||||||
voteBSignBytes := account.SignBytes(&tx.VoteB)
|
voteBSignBytes := account.SignBytes(&tx.VoteB)
|
||||||
if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
|
if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
|
||||||
@ -490,11 +500,12 @@ func (s *State) AppendBlock(block *blk.Block, blockPartsHeader blk.PartSetHeader
|
|||||||
return errors.New("Block at height 1 (first block) should have no Validation commits")
|
return errors.New("Block at height 1 (first block) should have no Validation commits")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if uint(len(block.Validation.Commits)) != s.BondedValidators.Size() {
|
if uint(len(block.Validation.Commits)) != s.LastBondedValidators.Size() {
|
||||||
return errors.New("Invalid block validation size")
|
return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
|
||||||
|
s.LastBondedValidators.Size(), len(block.Validation.Commits)))
|
||||||
}
|
}
|
||||||
var sumVotingPower uint64
|
var sumVotingPower uint64
|
||||||
s.BondedValidators.Iterate(func(index uint, val *Validator) bool {
|
s.LastBondedValidators.Iterate(func(index uint, val *Validator) bool {
|
||||||
commit := block.Validation.Commits[index]
|
commit := block.Validation.Commits[index]
|
||||||
if commit.IsZero() {
|
if commit.IsZero() {
|
||||||
return false
|
return false
|
||||||
@ -519,32 +530,45 @@ func (s *State) AppendBlock(block *blk.Block, blockPartsHeader blk.PartSetHeader
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if sumVotingPower <= s.BondedValidators.TotalVotingPower()*2/3 {
|
if sumVotingPower <= s.LastBondedValidators.TotalVotingPower()*2/3 {
|
||||||
return errors.New("Insufficient validation voting power")
|
return errors.New("Insufficient validation voting power")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit each tx
|
|
||||||
for _, tx := range block.Data.Txs {
|
|
||||||
err := s.ExecTx(tx)
|
|
||||||
if err != nil {
|
|
||||||
return InvalidTxError{tx, err}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Validator.LastCommitHeight as necessary.
|
// Update Validator.LastCommitHeight as necessary.
|
||||||
for i, commit := range block.Validation.Commits {
|
for i, commit := range block.Validation.Commits {
|
||||||
if commit.IsZero() {
|
if commit.IsZero() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, val := s.BondedValidators.GetByIndex(uint(i))
|
_, val := s.LastBondedValidators.GetByIndex(uint(i))
|
||||||
if val == nil {
|
if val == nil {
|
||||||
panic(Fmt("Failed to fetch validator at index %v", i))
|
panic(Fmt("Failed to fetch validator at index %v", i))
|
||||||
}
|
}
|
||||||
val.LastCommitHeight = block.Height - 1
|
if _, val_ := s.BondedValidators.GetByAddress(val.Address); val_ != nil {
|
||||||
updated := s.BondedValidators.Update(val)
|
val_.LastCommitHeight = block.Height - 1
|
||||||
|
updated := s.BondedValidators.Update(val_)
|
||||||
if !updated {
|
if !updated {
|
||||||
panic("Failed to update validator LastCommitHeight")
|
panic("Failed to update bonded validator LastCommitHeight")
|
||||||
|
}
|
||||||
|
} else if _, val_ := s.UnbondingValidators.GetByAddress(val.Address); val_ != nil {
|
||||||
|
val_.LastCommitHeight = block.Height - 1
|
||||||
|
updated := s.UnbondingValidators.Update(val_)
|
||||||
|
if !updated {
|
||||||
|
panic("Failed to update unbonding validator LastCommitHeight")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic("Could not find validator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember LastBondedValidators
|
||||||
|
s.LastBondedValidators = s.BondedValidators.Copy()
|
||||||
|
|
||||||
|
// Commit each tx
|
||||||
|
for _, tx := range block.Data.Txs {
|
||||||
|
err := s.ExecTx(tx)
|
||||||
|
if err != nil {
|
||||||
|
return InvalidTxError{tx, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user