Use BlockID everywhere

This commit is contained in:
Jae Kwon 2016-08-16 14:59:19 -07:00 committed by Ethan Buchman
parent 40791d886d
commit 1173a85c85
13 changed files with 162 additions and 181 deletions

View File

@ -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)

View File

@ -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")
} }
} }

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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
} }

View File

@ -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),

View File

@ -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)
}

View File

@ -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 {

View File

@ -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!

View File

@ -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)
} }

View File

@ -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))
}

View File

@ -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.