mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-30 09:12:14 +00:00
Use BlockID everywhere
This commit is contained in:
parent
40791d886d
commit
1173a85c85
@ -222,8 +222,11 @@ FOR_LOOP:
|
|||||||
firstParts := first.MakePartSet()
|
firstParts := first.MakePartSet()
|
||||||
firstPartsHeader := firstParts.Header()
|
firstPartsHeader := firstParts.Header()
|
||||||
// Finally, verify the first block using the second's commit
|
// Finally, verify the first block using the second's commit
|
||||||
|
// NOTE: we can probably make this more efficient, but note that calling
|
||||||
|
// first.Hash() doesn't verify the tx contents, so MakePartSet() is
|
||||||
|
// currently necessary.
|
||||||
err := bcR.state.Validators.VerifyCommit(
|
err := bcR.state.Validators.VerifyCommit(
|
||||||
bcR.state.ChainID, first.Hash(), firstPartsHeader, first.Height, second.LastCommit)
|
bcR.state.ChainID, types.BlockID{first.Hash(), firstPartsHeader}, first.Height, second.LastCommit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("error in validation", "error", err)
|
log.Info("error in validation", "error", err)
|
||||||
bcR.pool.RedoRequest(first.Height)
|
bcR.pool.RedoRequest(first.Height)
|
||||||
|
@ -45,8 +45,7 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS
|
|||||||
Height: vs.Height,
|
Height: vs.Height,
|
||||||
Round: vs.Round,
|
Round: vs.Round,
|
||||||
Type: voteType,
|
Type: voteType,
|
||||||
BlockHash: hash,
|
BlockID: types.BlockID{hash, header},
|
||||||
BlockPartsHeader: header,
|
|
||||||
}
|
}
|
||||||
err := vs.PrivValidator.SignVote(config.GetString("chain_id"), vote)
|
err := vs.PrivValidator.SignVote(config.GetString("chain_id"), vote)
|
||||||
return vote, err
|
return vote, err
|
||||||
@ -127,12 +126,12 @@ func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *valid
|
|||||||
panic("Failed to find prevote from validator")
|
panic("Failed to find prevote from validator")
|
||||||
}
|
}
|
||||||
if blockHash == nil {
|
if blockHash == nil {
|
||||||
if vote.BlockHash != nil {
|
if vote.BlockID.Hash != nil {
|
||||||
panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockHash))
|
panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockID.Hash))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !bytes.Equal(vote.BlockHash, blockHash) {
|
if !bytes.Equal(vote.BlockID.Hash, blockHash) {
|
||||||
panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockHash))
|
panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockID.Hash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,8 +142,8 @@ func validateLastPrecommit(t *testing.T, cs *ConsensusState, privVal *validatorS
|
|||||||
if vote = votes.GetByAddress(privVal.Address); vote == nil {
|
if vote = votes.GetByAddress(privVal.Address); vote == nil {
|
||||||
panic("Failed to find precommit from validator")
|
panic("Failed to find precommit from validator")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(vote.BlockHash, blockHash) {
|
if !bytes.Equal(vote.BlockID.Hash, blockHash) {
|
||||||
panic(fmt.Sprintf("Expected precommit to be for %X, got %X", blockHash, vote.BlockHash))
|
panic(fmt.Sprintf("Expected precommit to be for %X, got %X", blockHash, vote.BlockID.Hash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +155,11 @@ func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound in
|
|||||||
}
|
}
|
||||||
|
|
||||||
if votedBlockHash == nil {
|
if votedBlockHash == nil {
|
||||||
if vote.BlockHash != nil {
|
if vote.BlockID.Hash != nil {
|
||||||
panic("Expected precommit to be for nil")
|
panic("Expected precommit to be for nil")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !bytes.Equal(vote.BlockHash, votedBlockHash) {
|
if !bytes.Equal(vote.BlockID.Hash, votedBlockHash) {
|
||||||
panic("Expected precommit to be for proposal block")
|
panic("Expected precommit to be for proposal block")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func makeVoteHR(t *testing.T, height, round int, privVals []*types.PrivValidator
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: types.VoteTypePrecommit,
|
Type: types.VoteTypePrecommit,
|
||||||
BlockHash: []byte("fakehash"),
|
BlockID: types.BlockID{[]byte("fakehash"), types.PartSetHeader{}},
|
||||||
}
|
}
|
||||||
chainID := config.GetString("chain_id")
|
chainID := config.GetString("chain_id")
|
||||||
err := privVal.SignVote(chainID, vote)
|
err := privVal.SignVote(chainID, vote)
|
||||||
|
@ -68,7 +68,7 @@ func (cs *ConsensusState) readReplayMessage(msgBytes []byte, newStepCh chan inte
|
|||||||
case *VoteMessage:
|
case *VoteMessage:
|
||||||
v := msg.Vote
|
v := msg.Vote
|
||||||
log.Notice("Replay: Vote", "height", v.Height, "round", v.Round, "type", v.Type,
|
log.Notice("Replay: Vote", "height", v.Height, "round", v.Round, "type", v.Type,
|
||||||
"hash", v.BlockHash, "header", v.BlockPartsHeader, "peer", peerKey)
|
"blockID", v.BlockID, "peer", peerKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.handleMsg(m, cs.RoundState)
|
cs.handleMsg(m, cs.RoundState)
|
||||||
|
@ -476,7 +476,7 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) {
|
|||||||
if precommit == nil {
|
if precommit == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// XXXX reconstruct Vote from precommit after changing precommit to simpler
|
// XXX reconstruct Vote from precommit after changing precommit to simpler
|
||||||
// structure.
|
// structure.
|
||||||
added, err := lastPrecommits.AddVote(precommit)
|
added, err := lastPrecommits.AddVote(precommit)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
@ -922,8 +922,7 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
|
|||||||
Height: cs.Height,
|
Height: cs.Height,
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
NumTxs: len(txs),
|
NumTxs: len(txs),
|
||||||
LastBlockHash: cs.state.LastBlockHash,
|
LastBlockID: cs.state.LastBlockID,
|
||||||
LastBlockParts: cs.state.LastBlockParts,
|
|
||||||
ValidatorsHash: cs.state.Validators.Hash(),
|
ValidatorsHash: cs.state.Validators.Hash(),
|
||||||
AppHash: cs.state.AppHash, // state merkle root of txs from the previous block.
|
AppHash: cs.state.AppHash, // state merkle root of txs from the previous block.
|
||||||
},
|
},
|
||||||
@ -1048,7 +1047,7 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
|||||||
cs.newStep()
|
cs.newStep()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
hash, partsHeader, ok := cs.Votes.Prevotes(round).TwoThirdsMajority()
|
blockID, ok := cs.Votes.Prevotes(round).TwoThirdsMajority()
|
||||||
|
|
||||||
// If we don't have a polka, we must precommit nil
|
// If we don't have a polka, we must precommit nil
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1070,7 +1069,7 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// +2/3 prevoted nil. Unlock and precommit nil.
|
// +2/3 prevoted nil. Unlock and precommit nil.
|
||||||
if len(hash) == 0 {
|
if len(blockID.Hash) == 0 {
|
||||||
if cs.LockedBlock == nil {
|
if cs.LockedBlock == nil {
|
||||||
log.Notice("enterPrecommit: +2/3 prevoted for nil.")
|
log.Notice("enterPrecommit: +2/3 prevoted for nil.")
|
||||||
} else {
|
} else {
|
||||||
@ -1087,17 +1086,17 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
|||||||
// At this point, +2/3 prevoted for a particular block.
|
// At this point, +2/3 prevoted for a particular block.
|
||||||
|
|
||||||
// If we're already locked on that block, precommit it, and update the LockedRound
|
// If we're already locked on that block, precommit it, and update the LockedRound
|
||||||
if cs.LockedBlock.HashesTo(hash) {
|
if cs.LockedBlock.HashesTo(blockID.Hash) {
|
||||||
log.Notice("enterPrecommit: +2/3 prevoted locked block. Relocking")
|
log.Notice("enterPrecommit: +2/3 prevoted locked block. Relocking")
|
||||||
cs.LockedRound = round
|
cs.LockedRound = round
|
||||||
types.FireEventRelock(cs.evsw, cs.RoundStateEvent())
|
types.FireEventRelock(cs.evsw, cs.RoundStateEvent())
|
||||||
cs.signAddVote(types.VoteTypePrecommit, hash, partsHeader)
|
cs.signAddVote(types.VoteTypePrecommit, blockID.Hash, blockID.PartsHeader)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If +2/3 prevoted for proposal block, stage and precommit it
|
// If +2/3 prevoted for proposal block, stage and precommit it
|
||||||
if cs.ProposalBlock.HashesTo(hash) {
|
if cs.ProposalBlock.HashesTo(blockID.Hash) {
|
||||||
log.Notice("enterPrecommit: +2/3 prevoted proposal block. Locking", "hash", hash)
|
log.Notice("enterPrecommit: +2/3 prevoted proposal block. Locking", "hash", blockID.Hash)
|
||||||
// Validate the block.
|
// Validate the block.
|
||||||
if err := cs.state.ValidateBlock(cs.ProposalBlock); err != nil {
|
if err := cs.state.ValidateBlock(cs.ProposalBlock); err != nil {
|
||||||
PanicConsensus(Fmt("enterPrecommit: +2/3 prevoted for an invalid block: %v", err))
|
PanicConsensus(Fmt("enterPrecommit: +2/3 prevoted for an invalid block: %v", err))
|
||||||
@ -1106,7 +1105,7 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
|||||||
cs.LockedBlock = cs.ProposalBlock
|
cs.LockedBlock = cs.ProposalBlock
|
||||||
cs.LockedBlockParts = cs.ProposalBlockParts
|
cs.LockedBlockParts = cs.ProposalBlockParts
|
||||||
types.FireEventLock(cs.evsw, cs.RoundStateEvent())
|
types.FireEventLock(cs.evsw, cs.RoundStateEvent())
|
||||||
cs.signAddVote(types.VoteTypePrecommit, hash, partsHeader)
|
cs.signAddVote(types.VoteTypePrecommit, blockID.Hash, blockID.PartsHeader)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,9 +1116,9 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
|||||||
cs.LockedRound = 0
|
cs.LockedRound = 0
|
||||||
cs.LockedBlock = nil
|
cs.LockedBlock = nil
|
||||||
cs.LockedBlockParts = nil
|
cs.LockedBlockParts = nil
|
||||||
if !cs.ProposalBlockParts.HasHeader(partsHeader) {
|
if !cs.ProposalBlockParts.HasHeader(blockID.PartsHeader) {
|
||||||
cs.ProposalBlock = nil
|
cs.ProposalBlock = nil
|
||||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(partsHeader)
|
cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader)
|
||||||
}
|
}
|
||||||
types.FireEventUnlock(cs.evsw, cs.RoundStateEvent())
|
types.FireEventUnlock(cs.evsw, cs.RoundStateEvent())
|
||||||
cs.signAddVote(types.VoteTypePrecommit, nil, types.PartSetHeader{})
|
cs.signAddVote(types.VoteTypePrecommit, nil, types.PartSetHeader{})
|
||||||
@ -1167,7 +1166,7 @@ func (cs *ConsensusState) enterCommit(height int, commitRound int) {
|
|||||||
cs.tryFinalizeCommit(height)
|
cs.tryFinalizeCommit(height)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
hash, partsHeader, ok := cs.Votes.Precommits(commitRound).TwoThirdsMajority()
|
blockID, ok := cs.Votes.Precommits(commitRound).TwoThirdsMajority()
|
||||||
if !ok {
|
if !ok {
|
||||||
PanicSanity("RunActionCommit() expects +2/3 precommits")
|
PanicSanity("RunActionCommit() expects +2/3 precommits")
|
||||||
}
|
}
|
||||||
@ -1175,18 +1174,18 @@ func (cs *ConsensusState) enterCommit(height int, commitRound int) {
|
|||||||
// The Locked* fields no longer matter.
|
// The Locked* fields no longer matter.
|
||||||
// Move them over to ProposalBlock if they match the commit hash,
|
// Move them over to ProposalBlock if they match the commit hash,
|
||||||
// otherwise they'll be cleared in updateToState.
|
// otherwise they'll be cleared in updateToState.
|
||||||
if cs.LockedBlock.HashesTo(hash) {
|
if cs.LockedBlock.HashesTo(blockID.Hash) {
|
||||||
cs.ProposalBlock = cs.LockedBlock
|
cs.ProposalBlock = cs.LockedBlock
|
||||||
cs.ProposalBlockParts = cs.LockedBlockParts
|
cs.ProposalBlockParts = cs.LockedBlockParts
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have the block being committed, set up to get it.
|
// If we don't have the block being committed, set up to get it.
|
||||||
if !cs.ProposalBlock.HashesTo(hash) {
|
if !cs.ProposalBlock.HashesTo(blockID.Hash) {
|
||||||
if !cs.ProposalBlockParts.HasHeader(partsHeader) {
|
if !cs.ProposalBlockParts.HasHeader(blockID.PartsHeader) {
|
||||||
// We're getting the wrong block.
|
// We're getting the wrong block.
|
||||||
// Set up ProposalBlockParts and keep waiting.
|
// Set up ProposalBlockParts and keep waiting.
|
||||||
cs.ProposalBlock = nil
|
cs.ProposalBlock = nil
|
||||||
cs.ProposalBlockParts = types.NewPartSetFromHeader(partsHeader)
|
cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader)
|
||||||
} else {
|
} else {
|
||||||
// We just need to keep waiting.
|
// We just need to keep waiting.
|
||||||
}
|
}
|
||||||
@ -1199,12 +1198,12 @@ func (cs *ConsensusState) tryFinalizeCommit(height int) {
|
|||||||
PanicSanity(Fmt("tryFinalizeCommit() cs.Height: %v vs height: %v", cs.Height, height))
|
PanicSanity(Fmt("tryFinalizeCommit() cs.Height: %v vs height: %v", cs.Height, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, _, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
|
blockID, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
|
||||||
if !ok || len(hash) == 0 {
|
if !ok || len(blockID.Hash) == 0 {
|
||||||
log.Warn("Attempt to finalize failed. There was no +2/3 majority, or +2/3 was for <nil>.")
|
log.Warn("Attempt to finalize failed. There was no +2/3 majority, or +2/3 was for <nil>.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !cs.ProposalBlock.HashesTo(hash) {
|
if !cs.ProposalBlock.HashesTo(blockID.Hash) {
|
||||||
// TODO: this happens every time if we're not a validator (ugly logs)
|
// TODO: this happens every time if we're not a validator (ugly logs)
|
||||||
// TODO: ^^ wait, why does it matter that we're a validator?
|
// TODO: ^^ wait, why does it matter that we're a validator?
|
||||||
log.Warn("Attempt to finalize failed. We don't have the commit block.")
|
log.Warn("Attempt to finalize failed. We don't have the commit block.")
|
||||||
@ -1221,16 +1220,16 @@ func (cs *ConsensusState) finalizeCommit(height int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, header, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
|
blockID, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
|
||||||
block, blockParts := cs.ProposalBlock, cs.ProposalBlockParts
|
block, blockParts := cs.ProposalBlock, cs.ProposalBlockParts
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
PanicSanity(Fmt("Cannot finalizeCommit, commit does not have two thirds majority"))
|
PanicSanity(Fmt("Cannot finalizeCommit, commit does not have two thirds majority"))
|
||||||
}
|
}
|
||||||
if !blockParts.HasHeader(header) {
|
if !blockParts.HasHeader(blockID.PartsHeader) {
|
||||||
PanicSanity(Fmt("Expected ProposalBlockParts header to be commit header"))
|
PanicSanity(Fmt("Expected ProposalBlockParts header to be commit header"))
|
||||||
}
|
}
|
||||||
if !block.HashesTo(hash) {
|
if !block.HashesTo(blockID.Hash) {
|
||||||
PanicSanity(Fmt("Cannot finalizeCommit, ProposalBlock does not hash to commit hash"))
|
PanicSanity(Fmt("Cannot finalizeCommit, ProposalBlock does not hash to commit hash"))
|
||||||
}
|
}
|
||||||
if err := cs.state.ValidateBlock(block); err != nil {
|
if err := cs.state.ValidateBlock(block); err != nil {
|
||||||
@ -1461,8 +1460,8 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerKey string) (added bool,
|
|||||||
// we'll still enterNewRound(H,vote.R) and enterPrecommit(H,vote.R) to process it
|
// we'll still enterNewRound(H,vote.R) and enterPrecommit(H,vote.R) to process it
|
||||||
// there.
|
// there.
|
||||||
if (cs.LockedBlock != nil) && (cs.LockedRound < vote.Round) && (vote.Round <= cs.Round) {
|
if (cs.LockedBlock != nil) && (cs.LockedRound < vote.Round) && (vote.Round <= cs.Round) {
|
||||||
hash, _, ok := prevotes.TwoThirdsMajority()
|
blockID, ok := prevotes.TwoThirdsMajority()
|
||||||
if ok && !cs.LockedBlock.HashesTo(hash) {
|
if ok && !cs.LockedBlock.HashesTo(blockID.Hash) {
|
||||||
log.Notice("Unlocking because of POL.", "lockedRound", cs.LockedRound, "POLRound", vote.Round)
|
log.Notice("Unlocking because of POL.", "lockedRound", cs.LockedRound, "POLRound", vote.Round)
|
||||||
cs.LockedRound = 0
|
cs.LockedRound = 0
|
||||||
cs.LockedBlock = nil
|
cs.LockedBlock = nil
|
||||||
@ -1488,9 +1487,9 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerKey string) (added bool,
|
|||||||
case types.VoteTypePrecommit:
|
case types.VoteTypePrecommit:
|
||||||
precommits := cs.Votes.Precommits(vote.Round)
|
precommits := cs.Votes.Precommits(vote.Round)
|
||||||
log.Info("Added to precommit", "vote", vote, "precommits", precommits.StringShort())
|
log.Info("Added to precommit", "vote", vote, "precommits", precommits.StringShort())
|
||||||
hash, _, ok := precommits.TwoThirdsMajority()
|
blockID, ok := precommits.TwoThirdsMajority()
|
||||||
if ok {
|
if ok {
|
||||||
if len(hash) == 0 {
|
if len(blockID.Hash) == 0 {
|
||||||
cs.enterNewRound(height, vote.Round+1)
|
cs.enterNewRound(height, vote.Round+1)
|
||||||
} else {
|
} else {
|
||||||
cs.enterNewRound(height, vote.Round)
|
cs.enterNewRound(height, vote.Round)
|
||||||
@ -1527,8 +1526,7 @@ func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSet
|
|||||||
Height: cs.Height,
|
Height: cs.Height,
|
||||||
Round: cs.Round,
|
Round: cs.Round,
|
||||||
Type: type_,
|
Type: type_,
|
||||||
BlockHash: hash,
|
BlockID: types.BlockID{hash, header},
|
||||||
BlockPartsHeader: header,
|
|
||||||
}
|
}
|
||||||
err := cs.privValidator.SignVote(cs.state.ChainID, vote)
|
err := cs.privValidator.SignVote(cs.state.ChainID, vote)
|
||||||
return vote, err
|
return vote, err
|
||||||
|
@ -43,8 +43,7 @@ func (s *State) ExecBlock(eventCache types.Fireable, proxyAppConn proxy.AppConnC
|
|||||||
// All good!
|
// All good!
|
||||||
nextValSet.IncrementAccum(1)
|
nextValSet.IncrementAccum(1)
|
||||||
s.LastBlockHeight = block.Height
|
s.LastBlockHeight = block.Height
|
||||||
s.LastBlockHash = block.Hash()
|
s.LastBlockID = types.BlockID{block.Hash(), blockPartsHeader}
|
||||||
s.LastBlockParts = blockPartsHeader
|
|
||||||
s.LastBlockTime = block.Time
|
s.LastBlockTime = block.Time
|
||||||
s.Validators = nextValSet
|
s.Validators = nextValSet
|
||||||
s.LastValidators = valSet
|
s.LastValidators = valSet
|
||||||
@ -119,7 +118,7 @@ func (s *State) execBlockOnProxyApp(eventCache types.Fireable, proxyAppConn prox
|
|||||||
|
|
||||||
func (s *State) validateBlock(block *types.Block) error {
|
func (s *State) validateBlock(block *types.Block) error {
|
||||||
// Basic block validation.
|
// Basic block validation.
|
||||||
err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, s.LastBlockHash, s.LastBlockParts, s.LastBlockTime, s.AppHash)
|
err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, s.LastBlockID, s.LastBlockTime, s.AppHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -135,7 +134,7 @@ func (s *State) validateBlock(block *types.Block) error {
|
|||||||
s.LastValidators.Size(), len(block.LastCommit.Precommits))
|
s.LastValidators.Size(), len(block.LastCommit.Precommits))
|
||||||
}
|
}
|
||||||
err := s.LastValidators.VerifyCommit(
|
err := s.LastValidators.VerifyCommit(
|
||||||
s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastCommit)
|
s.ChainID, s.LastBlockID, block.Height-1, block.LastCommit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@ type State struct {
|
|||||||
GenesisDoc *types.GenesisDoc
|
GenesisDoc *types.GenesisDoc
|
||||||
ChainID string
|
ChainID string
|
||||||
LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
|
LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
|
||||||
LastBlockHash []byte
|
LastBlockID types.BlockID
|
||||||
LastBlockParts types.PartSetHeader
|
|
||||||
LastBlockTime time.Time
|
LastBlockTime time.Time
|
||||||
Validators *types.ValidatorSet
|
Validators *types.ValidatorSet
|
||||||
LastValidators *types.ValidatorSet
|
LastValidators *types.ValidatorSet
|
||||||
@ -56,8 +55,7 @@ func (s *State) Copy() *State {
|
|||||||
GenesisDoc: s.GenesisDoc,
|
GenesisDoc: s.GenesisDoc,
|
||||||
ChainID: s.ChainID,
|
ChainID: s.ChainID,
|
||||||
LastBlockHeight: s.LastBlockHeight,
|
LastBlockHeight: s.LastBlockHeight,
|
||||||
LastBlockHash: s.LastBlockHash,
|
LastBlockID: s.LastBlockID,
|
||||||
LastBlockParts: s.LastBlockParts,
|
|
||||||
LastBlockTime: s.LastBlockTime,
|
LastBlockTime: s.LastBlockTime,
|
||||||
Validators: s.Validators.Copy(),
|
Validators: s.Validators.Copy(),
|
||||||
LastValidators: s.LastValidators.Copy(),
|
LastValidators: s.LastValidators.Copy(),
|
||||||
@ -117,8 +115,7 @@ func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
|
|||||||
GenesisDoc: genDoc,
|
GenesisDoc: genDoc,
|
||||||
ChainID: genDoc.ChainID,
|
ChainID: genDoc.ChainID,
|
||||||
LastBlockHeight: 0,
|
LastBlockHeight: 0,
|
||||||
LastBlockHash: nil,
|
LastBlockID: types.BlockID{},
|
||||||
LastBlockParts: types.PartSetHeader{},
|
|
||||||
LastBlockTime: genDoc.GenesisTime,
|
LastBlockTime: genDoc.GenesisTime,
|
||||||
Validators: types.NewValidatorSet(validators),
|
Validators: types.NewValidatorSet(validators),
|
||||||
LastValidators: types.NewValidatorSet(nil),
|
LastValidators: types.NewValidatorSet(nil),
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,8 +22,8 @@ type Block struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Basic validation that doesn't involve state data.
|
// Basic validation that doesn't involve state data.
|
||||||
func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockHash []byte,
|
func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockID BlockID,
|
||||||
lastBlockParts PartSetHeader, lastBlockTime time.Time, appHash []byte) error {
|
lastBlockTime time.Time, appHash []byte) error {
|
||||||
if b.ChainID != chainID {
|
if b.ChainID != chainID {
|
||||||
return errors.New(Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", chainID, b.ChainID))
|
return errors.New(Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", chainID, b.ChainID))
|
||||||
}
|
}
|
||||||
@ -39,11 +40,8 @@ func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockHash
|
|||||||
if b.NumTxs != len(b.Data.Txs) {
|
if b.NumTxs != len(b.Data.Txs) {
|
||||||
return errors.New(Fmt("Wrong Block.Header.NumTxs. Expected %v, got %v", len(b.Data.Txs), b.NumTxs))
|
return errors.New(Fmt("Wrong Block.Header.NumTxs. Expected %v, got %v", len(b.Data.Txs), b.NumTxs))
|
||||||
}
|
}
|
||||||
if !bytes.Equal(b.LastBlockHash, lastBlockHash) {
|
if !b.LastBlockID.Equals(lastBlockID) {
|
||||||
return errors.New(Fmt("Wrong Block.Header.LastBlockHash. Expected %X, got %X", lastBlockHash, b.LastBlockHash))
|
return errors.New(Fmt("Wrong Block.Header.LastBlockID. Expected %v, got %v", lastBlockID, b.LastBlockID))
|
||||||
}
|
|
||||||
if !b.LastBlockParts.Equals(lastBlockParts) {
|
|
||||||
return errors.New(Fmt("Wrong Block.Header.LastBlockParts. Expected %v, got %v", lastBlockParts, b.LastBlockParts))
|
|
||||||
}
|
}
|
||||||
if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
|
if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
|
||||||
return errors.New(Fmt("Wrong Block.Header.LastCommitHash. Expected %X, got %X", b.LastCommitHash, b.LastCommit.Hash()))
|
return errors.New(Fmt("Wrong Block.Header.LastCommitHash. Expected %X, got %X", b.LastCommitHash, b.LastCommit.Hash()))
|
||||||
@ -134,8 +132,7 @@ type Header struct {
|
|||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
Time time.Time `json:"time"`
|
Time time.Time `json:"time"`
|
||||||
NumTxs int `json:"num_txs"`
|
NumTxs int `json:"num_txs"`
|
||||||
LastBlockHash []byte `json:"last_block_hash"`
|
LastBlockID BlockID `json:"last_block_id"`
|
||||||
LastBlockParts PartSetHeader `json:"last_block_parts"`
|
|
||||||
LastCommitHash []byte `json:"last_commit_hash"`
|
LastCommitHash []byte `json:"last_commit_hash"`
|
||||||
DataHash []byte `json:"data_hash"`
|
DataHash []byte `json:"data_hash"`
|
||||||
ValidatorsHash []byte `json:"validators_hash"`
|
ValidatorsHash []byte `json:"validators_hash"`
|
||||||
@ -152,8 +149,7 @@ func (h *Header) Hash() []byte {
|
|||||||
"Height": h.Height,
|
"Height": h.Height,
|
||||||
"Time": h.Time,
|
"Time": h.Time,
|
||||||
"NumTxs": h.NumTxs,
|
"NumTxs": h.NumTxs,
|
||||||
"LastBlock": h.LastBlockHash,
|
"LastBlockID": h.LastBlockID,
|
||||||
"LastBlockParts": h.LastBlockParts,
|
|
||||||
"LastCommit": h.LastCommitHash,
|
"LastCommit": h.LastCommitHash,
|
||||||
"Data": h.DataHash,
|
"Data": h.DataHash,
|
||||||
"Validators": h.ValidatorsHash,
|
"Validators": h.ValidatorsHash,
|
||||||
@ -170,8 +166,7 @@ func (h *Header) StringIndented(indent string) string {
|
|||||||
%s Height: %v
|
%s Height: %v
|
||||||
%s Time: %v
|
%s Time: %v
|
||||||
%s NumTxs: %v
|
%s NumTxs: %v
|
||||||
%s LastBlock: %X
|
%s LastBlockID: %v
|
||||||
%s LastBlockParts: %v
|
|
||||||
%s LastCommit: %X
|
%s LastCommit: %X
|
||||||
%s Data: %X
|
%s Data: %X
|
||||||
%s Validators: %X
|
%s Validators: %X
|
||||||
@ -181,8 +176,7 @@ func (h *Header) StringIndented(indent string) string {
|
|||||||
indent, h.Height,
|
indent, h.Height,
|
||||||
indent, h.Time,
|
indent, h.Time,
|
||||||
indent, h.NumTxs,
|
indent, h.NumTxs,
|
||||||
indent, h.LastBlockHash,
|
indent, h.LastBlockID,
|
||||||
indent, h.LastBlockParts,
|
|
||||||
indent, h.LastCommitHash,
|
indent, h.LastCommitHash,
|
||||||
indent, h.DataHash,
|
indent, h.DataHash,
|
||||||
indent, h.ValidatorsHash,
|
indent, h.ValidatorsHash,
|
||||||
@ -360,3 +354,33 @@ func (data *Data) StringIndented(indent string) string {
|
|||||||
indent, strings.Join(txStrings, "\n"+indent+" "),
|
indent, strings.Join(txStrings, "\n"+indent+" "),
|
||||||
indent, data.hash)
|
indent, data.hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BlockID struct {
|
||||||
|
Hash []byte `json:"hash"`
|
||||||
|
PartsHeader PartSetHeader `json:"parts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (blockID BlockID) IsZero() bool {
|
||||||
|
return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (blockID BlockID) Equals(other BlockID) bool {
|
||||||
|
return bytes.Equal(blockID.Hash, other.Hash) &&
|
||||||
|
blockID.PartsHeader.Equals(other.PartsHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (blockID BlockID) Key() string {
|
||||||
|
return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
|
||||||
|
wire.WriteTo([]byte(Fmt(`{"hash":"%X","parts":`, blockID.Hash)), w, n, err)
|
||||||
|
blockID.PartsHeader.WriteSignBytes(w, n, err)
|
||||||
|
wire.WriteTo([]byte("}"), w, n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (blockID BlockID) String() string {
|
||||||
|
return fmt.Sprintf(`%X:%v`, blockID.Hash, blockID.PartsHeader)
|
||||||
|
}
|
||||||
|
@ -66,7 +66,7 @@ type PartSetHeader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (psh PartSetHeader) String() string {
|
func (psh PartSetHeader) String() string {
|
||||||
return fmt.Sprintf("PartSet{T:%v %X}", psh.Total, Fingerprint(psh.Hash))
|
return fmt.Sprintf("%v:%X", psh.Total, Fingerprint(psh.Hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (psh PartSetHeader) IsZero() bool {
|
func (psh PartSetHeader) IsZero() bool {
|
||||||
|
@ -206,8 +206,7 @@ func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify that +2/3 of the set had signed the given signBytes
|
// Verify that +2/3 of the set had signed the given signBytes
|
||||||
func (valSet *ValidatorSet) VerifyCommit(chainID string,
|
func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height int, commit *Commit) error {
|
||||||
hash []byte, parts PartSetHeader, height int, commit *Commit) error {
|
|
||||||
if valSet.Size() != len(commit.Precommits) {
|
if valSet.Size() != len(commit.Precommits) {
|
||||||
return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits))
|
return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits))
|
||||||
}
|
}
|
||||||
@ -238,10 +237,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string,
|
|||||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||||
return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit)
|
return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(precommit.BlockHash, hash) {
|
if !blockID.Equals(precommit.BlockID) {
|
||||||
continue // Not an error, but doesn't count
|
|
||||||
}
|
|
||||||
if !parts.Equals(precommit.BlockPartsHeader) {
|
|
||||||
continue // Not an error, but doesn't count
|
continue // Not an error, but doesn't count
|
||||||
}
|
}
|
||||||
// Good precommit!
|
// Good precommit!
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -35,8 +34,7 @@ type Vote struct {
|
|||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
Round int `json:"round"`
|
Round int `json:"round"`
|
||||||
Type byte `json:"type"`
|
Type byte `json:"type"`
|
||||||
BlockHash []byte `json:"block_hash"` // empty if vote is nil.
|
BlockID BlockID `json:"block_id"` // zero if vote is nil.
|
||||||
BlockPartsHeader PartSetHeader `json:"block_parts_header"` // zero if vote is nil.
|
|
||||||
Signature crypto.SignatureEd25519 `json:"signature"`
|
Signature crypto.SignatureEd25519 `json:"signature"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +46,8 @@ const (
|
|||||||
|
|
||||||
func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
|
func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
|
||||||
wire.WriteTo([]byte(Fmt(`{"chain_id":"%s"`, chainID)), w, n, err)
|
wire.WriteTo([]byte(Fmt(`{"chain_id":"%s"`, chainID)), w, n, err)
|
||||||
wire.WriteTo([]byte(Fmt(`,"vote":{"block_hash":"%X","block_parts_header":%v`, vote.BlockHash, vote.BlockPartsHeader)), w, n, err)
|
wire.WriteTo([]byte(`,"vote":{"block_id":`), w, n, err)
|
||||||
|
vote.BlockID.WriteSignBytes(w, n, err)
|
||||||
wire.WriteTo([]byte(Fmt(`,"height":%v,"round":%v,"type":%v}}`, vote.Height, vote.Round, vote.Type)), w, n, err)
|
wire.WriteTo([]byte(Fmt(`,"height":%v,"round":%v,"type":%v}}`, vote.Height, vote.Round, vote.Type)), w, n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,12 +73,5 @@ func (vote *Vote) String() string {
|
|||||||
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %v}",
|
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %v}",
|
||||||
vote.ValidatorIndex, Fingerprint(vote.ValidatorAddress),
|
vote.ValidatorIndex, Fingerprint(vote.ValidatorAddress),
|
||||||
vote.Height, vote.Round, vote.Type, typeString,
|
vote.Height, vote.Round, vote.Type, typeString,
|
||||||
Fingerprint(vote.BlockHash), vote.Signature)
|
Fingerprint(vote.BlockID.Hash), vote.Signature)
|
||||||
}
|
|
||||||
|
|
||||||
// Does not check signature, but checks for equality of block
|
|
||||||
// NOTE: May be from different validators, and signature may be incorrect.
|
|
||||||
func (vote *Vote) SameBlockAs(other *Vote) bool {
|
|
||||||
return bytes.Equal(vote.BlockHash, other.BlockHash) &&
|
|
||||||
vote.BlockPartsHeader.Equals(other.BlockPartsHeader)
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
. "github.com/tendermint/go-common"
|
. "github.com/tendermint/go-common"
|
||||||
"github.com/tendermint/go-wire"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -55,9 +54,9 @@ type VoteSet struct {
|
|||||||
votesBitArray *BitArray
|
votesBitArray *BitArray
|
||||||
votes []*Vote // Primary votes to share
|
votes []*Vote // Primary votes to share
|
||||||
sum int64 // Sum of voting power for seen votes, discounting conflicts
|
sum int64 // Sum of voting power for seen votes, discounting conflicts
|
||||||
maj23 *blockInfo // First 2/3 majority seen
|
maj23 *BlockID // First 2/3 majority seen
|
||||||
votesByBlock map[string]*blockVotes // string(blockHash|blockParts) -> blockVotes
|
votesByBlock map[string]*blockVotes // string(blockHash|blockParts) -> blockVotes
|
||||||
peerMaj23s map[string]*blockInfo // Maj23 for each peer
|
peerMaj23s map[string]BlockID // Maj23 for each peer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new VoteSet struct used to accumulate votes for given height/round.
|
// Constructs a new VoteSet struct used to accumulate votes for given height/round.
|
||||||
@ -76,7 +75,7 @@ func NewVoteSet(chainID string, height int, round int, type_ byte, valSet *Valid
|
|||||||
sum: 0,
|
sum: 0,
|
||||||
maj23: nil,
|
maj23: nil,
|
||||||
votesByBlock: make(map[string]*blockVotes, valSet.Size()),
|
votesByBlock: make(map[string]*blockVotes, valSet.Size()),
|
||||||
peerMaj23s: make(map[string]*blockInfo),
|
peerMaj23s: make(map[string]BlockID),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +133,7 @@ func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
|
|||||||
func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
||||||
valIndex := vote.ValidatorIndex
|
valIndex := vote.ValidatorIndex
|
||||||
valAddr := vote.ValidatorAddress
|
valAddr := vote.ValidatorAddress
|
||||||
blockKey := getBlockKey(vote)
|
blockKey := vote.BlockID.Key()
|
||||||
|
|
||||||
// Ensure that validator index was set
|
// Ensure that validator index was set
|
||||||
if valIndex < 0 || len(valAddr) == 0 {
|
if valIndex < 0 || len(valAddr) == 0 {
|
||||||
@ -192,7 +191,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
|||||||
|
|
||||||
// Returns (vote, true) if vote exists for valIndex and blockKey
|
// Returns (vote, true) if vote exists for valIndex and blockKey
|
||||||
func (voteSet *VoteSet) getVote(valIndex int, blockKey string) (vote *Vote, ok bool) {
|
func (voteSet *VoteSet) getVote(valIndex int, blockKey string) (vote *Vote, ok bool) {
|
||||||
if existing := voteSet.votes[valIndex]; existing != nil && getBlockKey(existing) == blockKey {
|
if existing := voteSet.votes[valIndex]; existing != nil && existing.BlockID.Key() == blockKey {
|
||||||
return existing, true
|
return existing, true
|
||||||
}
|
}
|
||||||
if existing := voteSet.votesByBlock[blockKey].getByIndex(valIndex); existing != nil {
|
if existing := voteSet.votesByBlock[blockKey].getByIndex(valIndex); existing != nil {
|
||||||
@ -208,13 +207,13 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
|
|||||||
|
|
||||||
// Already exists in voteSet.votes?
|
// Already exists in voteSet.votes?
|
||||||
if existing := voteSet.votes[valIndex]; existing != nil {
|
if existing := voteSet.votes[valIndex]; existing != nil {
|
||||||
if existing.SameBlockAs(vote) {
|
if existing.BlockID.Equals(vote.BlockID) {
|
||||||
PanicSanity("addVerifiedVote does not expect duplicate votes")
|
PanicSanity("addVerifiedVote does not expect duplicate votes")
|
||||||
} else {
|
} else {
|
||||||
conflicting = existing
|
conflicting = existing
|
||||||
}
|
}
|
||||||
// Replace vote if blockKey matches voteSet.maj23.
|
// Replace vote if blockKey matches voteSet.maj23.
|
||||||
if voteSet.maj23 != nil && voteSet.maj23.BlockKey() == blockKey {
|
if voteSet.maj23 != nil && voteSet.maj23.Key() == blockKey {
|
||||||
voteSet.votes[valIndex] = vote
|
voteSet.votes[valIndex] = vote
|
||||||
voteSet.votesBitArray.SetIndex(valIndex, true)
|
voteSet.votesBitArray.SetIndex(valIndex, true)
|
||||||
}
|
}
|
||||||
@ -259,7 +258,8 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
|
|||||||
if origSum < quorum && quorum <= votesByBlock.sum {
|
if origSum < quorum && quorum <= votesByBlock.sum {
|
||||||
// Only consider the first quorum reached
|
// Only consider the first quorum reached
|
||||||
if voteSet.maj23 == nil {
|
if voteSet.maj23 == nil {
|
||||||
voteSet.maj23 = getBlockInfo(vote)
|
maj23BlockID := vote.BlockID
|
||||||
|
voteSet.maj23 = &maj23BlockID
|
||||||
// And also copy votes over to voteSet.votes
|
// And also copy votes over to voteSet.votes
|
||||||
for i, vote := range votesByBlock.votes {
|
for i, vote := range votesByBlock.votes {
|
||||||
if vote != nil {
|
if vote != nil {
|
||||||
@ -276,22 +276,21 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
|
|||||||
// NOTE: if there are too many peers, or too much peer churn,
|
// NOTE: if there are too many peers, or too much peer churn,
|
||||||
// this can cause memory issues.
|
// this can cause memory issues.
|
||||||
// TODO: implement ability to remove peers too
|
// TODO: implement ability to remove peers too
|
||||||
func (voteSet *VoteSet) SetPeerMaj23(peerID string, blockHash []byte, blockPartsHeader PartSetHeader) {
|
func (voteSet *VoteSet) SetPeerMaj23(peerID string, blockID BlockID) {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
|
|
||||||
blockInfo := &blockInfo{blockHash, blockPartsHeader}
|
blockKey := blockID.Key()
|
||||||
blockKey := blockInfo.BlockKey()
|
|
||||||
|
|
||||||
// Make sure peer hasn't already told us something.
|
// Make sure peer hasn't already told us something.
|
||||||
if existing, ok := voteSet.peerMaj23s[peerID]; ok {
|
if existing, ok := voteSet.peerMaj23s[peerID]; ok {
|
||||||
if existing.Equals(blockInfo) {
|
if existing.Equals(blockID) {
|
||||||
return // Nothing to do
|
return // Nothing to do
|
||||||
} else {
|
} else {
|
||||||
return // TODO bad peer!
|
return // TODO bad peer!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
voteSet.peerMaj23s[peerID] = blockInfo
|
voteSet.peerMaj23s[peerID] = blockID
|
||||||
|
|
||||||
// Create .votesByBlock entry if needed.
|
// Create .votesByBlock entry if needed.
|
||||||
votesByBlock, ok := voteSet.votesByBlock[blockKey]
|
votesByBlock, ok := voteSet.votesByBlock[blockKey]
|
||||||
@ -367,13 +366,13 @@ func (voteSet *VoteSet) HasTwoThirdsAny() bool {
|
|||||||
|
|
||||||
// Returns either a blockhash (or nil) that received +2/3 majority.
|
// Returns either a blockhash (or nil) that received +2/3 majority.
|
||||||
// If there exists no such majority, returns (nil, PartSetHeader{}, false).
|
// If there exists no such majority, returns (nil, PartSetHeader{}, false).
|
||||||
func (voteSet *VoteSet) TwoThirdsMajority() (hash []byte, parts PartSetHeader, ok bool) {
|
func (voteSet *VoteSet) TwoThirdsMajority() (blockID BlockID, ok bool) {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
if voteSet.maj23 != nil {
|
if voteSet.maj23 != nil {
|
||||||
return voteSet.maj23.hash, voteSet.maj23.partsHeader, true
|
return *voteSet.maj23, true
|
||||||
} else {
|
} else {
|
||||||
return nil, PartSetHeader{}, false
|
return BlockID{}, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +429,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For every validator, get the precommit
|
// For every validator, get the precommit
|
||||||
maj23Votes := voteSet.votesByBlock[voteSet.maj23.BlockKey()]
|
maj23Votes := voteSet.votesByBlock[voteSet.maj23.Key()]
|
||||||
return &Commit{
|
return &Commit{
|
||||||
Precommits: maj23Votes.votes,
|
Precommits: maj23Votes.votes,
|
||||||
}
|
}
|
||||||
@ -488,27 +487,3 @@ type VoteSetReader interface {
|
|||||||
GetByIndex(int) *Vote
|
GetByIndex(int) *Vote
|
||||||
IsCommit() bool
|
IsCommit() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
type blockInfo struct {
|
|
||||||
hash []byte
|
|
||||||
partsHeader PartSetHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bInfo *blockInfo) Equals(other *blockInfo) bool {
|
|
||||||
return bytes.Equal(bInfo.hash, other.hash) &&
|
|
||||||
bInfo.partsHeader.Equals(other.partsHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bInfo *blockInfo) BlockKey() string {
|
|
||||||
return string(bInfo.hash) + string(wire.BinaryBytes(bInfo.partsHeader))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBlockInfo(vote *Vote) *blockInfo {
|
|
||||||
return &blockInfo{vote.BlockHash, vote.BlockPartsHeader}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBlockKey(vote *Vote) string {
|
|
||||||
return string(vote.BlockHash) + string(wire.BinaryBytes(vote.BlockPartsHeader))
|
|
||||||
}
|
|
||||||
|
@ -49,14 +49,14 @@ func withType(vote *Vote, type_ byte) *Vote {
|
|||||||
// Convenience: Return new vote with different blockHash
|
// Convenience: Return new vote with different blockHash
|
||||||
func withBlockHash(vote *Vote, blockHash []byte) *Vote {
|
func withBlockHash(vote *Vote, blockHash []byte) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockHash = blockHash
|
vote.BlockID.Hash = blockHash
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different blockParts
|
// Convenience: Return new vote with different blockParts
|
||||||
func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote {
|
func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockPartsHeader = blockPartsHeader
|
vote.BlockID.PartsHeader = blockPartsHeader
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ func TestAddVote(t *testing.T) {
|
|||||||
if voteSet.BitArray().GetIndex(0) {
|
if voteSet.BitArray().GetIndex(0) {
|
||||||
t.Errorf("Expected BitArray.GetIndex(0) to be false")
|
t.Errorf("Expected BitArray.GetIndex(0) to be false")
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
blockID, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ func TestAddVote(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrevote,
|
Type: VoteTypePrevote,
|
||||||
BlockHash: nil,
|
BlockID: BlockID{nil, PartSetHeader{}},
|
||||||
}
|
}
|
||||||
signAddVote(val0, vote, voteSet)
|
signAddVote(val0, vote, voteSet)
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ func TestAddVote(t *testing.T) {
|
|||||||
if !voteSet.BitArray().GetIndex(0) {
|
if !voteSet.BitArray().GetIndex(0) {
|
||||||
t.Errorf("Expected BitArray.GetIndex(0) to be true")
|
t.Errorf("Expected BitArray.GetIndex(0) to be true")
|
||||||
}
|
}
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,15 +116,15 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrevote,
|
Type: VoteTypePrevote,
|
||||||
BlockHash: nil,
|
BlockID: BlockID{nil, PartSetHeader{}},
|
||||||
}
|
}
|
||||||
// 6 out of 10 voted for nil.
|
// 6 out of 10 voted for nil.
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
vote := withValidator(voteProto, privValidators[i].Address, i)
|
vote := withValidator(voteProto, privValidators[i].Address, i)
|
||||||
signAddVote(privValidators[i], vote, voteSet)
|
signAddVote(privValidators[i], vote, voteSet)
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
blockID, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +132,8 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := withValidator(voteProto, privValidators[6].Address, 6)
|
vote := withValidator(voteProto, privValidators[6].Address, 6)
|
||||||
signAddVote(privValidators[6], withBlockHash(vote, RandBytes(32)), voteSet)
|
signAddVote(privValidators[6], withBlockHash(vote, RandBytes(32)), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,8 +142,8 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := withValidator(voteProto, privValidators[7].Address, 7)
|
vote := withValidator(voteProto, privValidators[7].Address, 7)
|
||||||
signAddVote(privValidators[7], vote, voteSet)
|
signAddVote(privValidators[7], vote, voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || !ok {
|
if !ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be 2/3 majority for nil")
|
t.Errorf("There should be 2/3 majority for nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,8 +163,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrevote,
|
Type: VoteTypePrevote,
|
||||||
BlockHash: blockHash,
|
BlockID: BlockID{blockHash, blockPartsHeader},
|
||||||
BlockPartsHeader: blockPartsHeader,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 66 out of 100 voted for nil.
|
// 66 out of 100 voted for nil.
|
||||||
@ -172,8 +171,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
vote := withValidator(voteProto, privValidators[i].Address, i)
|
vote := withValidator(voteProto, privValidators[i].Address, i)
|
||||||
signAddVote(privValidators[i], vote, voteSet)
|
signAddVote(privValidators[i], vote, voteSet)
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
blockID, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,8 +180,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := withValidator(voteProto, privValidators[66].Address, 66)
|
vote := withValidator(voteProto, privValidators[66].Address, 66)
|
||||||
signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
|
signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added was nil")
|
t.Errorf("There should be no 2/3 majority: last vote added was nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,8 +191,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
vote := withValidator(voteProto, privValidators[67].Address, 67)
|
vote := withValidator(voteProto, privValidators[67].Address, 67)
|
||||||
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
|
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
|
||||||
signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Hash")
|
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Hash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,8 +202,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
vote := withValidator(voteProto, privValidators[68].Address, 68)
|
vote := withValidator(voteProto, privValidators[68].Address, 68)
|
||||||
blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash}
|
blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash}
|
||||||
signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Total")
|
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Total")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,8 +212,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := withValidator(voteProto, privValidators[69].Address, 69)
|
vote := withValidator(voteProto, privValidators[69].Address, 69)
|
||||||
signAddVote(privValidators[69], withBlockHash(vote, RandBytes(32)), voteSet)
|
signAddVote(privValidators[69], withBlockHash(vote, RandBytes(32)), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if ok || !blockID.IsZero() {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different BlockHash")
|
t.Errorf("There should be no 2/3 majority: last vote added had different BlockHash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,8 +222,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := withValidator(voteProto, privValidators[70].Address, 70)
|
vote := withValidator(voteProto, privValidators[70].Address, 70)
|
||||||
signAddVote(privValidators[70], vote, voteSet)
|
signAddVote(privValidators[70], vote, voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
blockID, ok = voteSet.TwoThirdsMajority()
|
||||||
if !bytes.Equal(hash, blockHash) || !header.Equals(blockPartsHeader) || !ok {
|
if !ok || !blockID.Equals(BlockID{blockHash, blockPartsHeader}) {
|
||||||
t.Errorf("There should be 2/3 majority")
|
t.Errorf("There should be 2/3 majority")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +239,7 @@ func TestBadVotes(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrevote,
|
Type: VoteTypePrevote,
|
||||||
BlockHash: nil,
|
BlockID: BlockID{nil, PartSetHeader{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
// val0 votes for nil.
|
// val0 votes for nil.
|
||||||
@ -301,7 +300,7 @@ func TestConflicts(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrevote,
|
Type: VoteTypePrevote,
|
||||||
BlockHash: nil,
|
BlockID: BlockID{nil, PartSetHeader{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
// val0 votes for nil.
|
// val0 votes for nil.
|
||||||
@ -326,7 +325,7 @@ func TestConflicts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start tracking blockHash1
|
// start tracking blockHash1
|
||||||
voteSet.SetPeerMaj23("peerA", blockHash1, PartSetHeader{})
|
voteSet.SetPeerMaj23("peerA", BlockID{blockHash1, PartSetHeader{}})
|
||||||
|
|
||||||
// val0 votes again for blockHash1.
|
// val0 votes again for blockHash1.
|
||||||
{
|
{
|
||||||
@ -341,7 +340,7 @@ func TestConflicts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// attempt tracking blockHash2, should fail because already set for peerA.
|
// attempt tracking blockHash2, should fail because already set for peerA.
|
||||||
voteSet.SetPeerMaj23("peerA", blockHash2, PartSetHeader{})
|
voteSet.SetPeerMaj23("peerA", BlockID{blockHash2, PartSetHeader{}})
|
||||||
|
|
||||||
// val0 votes again for blockHash1.
|
// val0 votes again for blockHash1.
|
||||||
{
|
{
|
||||||
@ -390,7 +389,7 @@ func TestConflicts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now attempt tracking blockHash1
|
// now attempt tracking blockHash1
|
||||||
voteSet.SetPeerMaj23("peerB", blockHash1, PartSetHeader{})
|
voteSet.SetPeerMaj23("peerB", BlockID{blockHash1, PartSetHeader{}})
|
||||||
|
|
||||||
// val2 votes for blockHash1.
|
// val2 votes for blockHash1.
|
||||||
{
|
{
|
||||||
@ -408,8 +407,8 @@ func TestConflicts(t *testing.T) {
|
|||||||
if !voteSet.HasTwoThirdsMajority() {
|
if !voteSet.HasTwoThirdsMajority() {
|
||||||
t.Errorf("We should have 2/3 majority for blockHash1")
|
t.Errorf("We should have 2/3 majority for blockHash1")
|
||||||
}
|
}
|
||||||
blockHash23maj, _, _ := voteSet.TwoThirdsMajority()
|
blockIDMaj23, _ := voteSet.TwoThirdsMajority()
|
||||||
if !bytes.Equal(blockHash23maj, blockHash1) {
|
if !bytes.Equal(blockIDMaj23.Hash, blockHash1) {
|
||||||
t.Errorf("Got the wrong 2/3 majority blockhash")
|
t.Errorf("Got the wrong 2/3 majority blockhash")
|
||||||
}
|
}
|
||||||
if !voteSet.HasTwoThirdsAny() {
|
if !voteSet.HasTwoThirdsAny() {
|
||||||
@ -429,8 +428,7 @@ func TestMakeCommit(t *testing.T) {
|
|||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: VoteTypePrecommit,
|
Type: VoteTypePrecommit,
|
||||||
BlockHash: blockHash,
|
BlockID: BlockID{blockHash, blockPartsHeader},
|
||||||
BlockPartsHeader: blockPartsHeader,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6 out of 10 voted for some block.
|
// 6 out of 10 voted for some block.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user