mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-04 17:11:19 +00:00
WIP: exploring changes related to proposed ADR:
https://github.com/tendermint/tendermint/pull/2445 - still contains a lot of failing tests etc
This commit is contained in:
parent
6ddc0199ef
commit
d54c09dd67
@ -69,7 +69,7 @@ var (
|
|||||||
partSet = block.MakePartSet(2)
|
partSet = block.MakePartSet(2)
|
||||||
part1 = partSet.GetPart(0)
|
part1 = partSet.GetPart(0)
|
||||||
part2 = partSet.GetPart(1)
|
part2 = partSet.GetPart(1)
|
||||||
seenCommit1 = &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit1 = &types.Commit{Precommits: []*types.UnsignedVote{{Height: 10,
|
||||||
Timestamp: tmtime.Now()}}}
|
Timestamp: tmtime.Now()}}}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
|||||||
// save a block
|
// save a block
|
||||||
block := makeBlock(bs.Height()+1, state)
|
block := makeBlock(bs.Height()+1, state)
|
||||||
validPartSet := block.MakePartSet(2)
|
validPartSet := block.MakePartSet(2)
|
||||||
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit := &types.Commit{Precommits: []*types.UnsignedVote{{Height: 10,
|
||||||
Timestamp: tmtime.Now()}}}
|
Timestamp: tmtime.Now()}}}
|
||||||
bs.SaveBlock(block, partSet, seenCommit)
|
bs.SaveBlock(block, partSet, seenCommit)
|
||||||
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
||||||
@ -110,7 +110,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
|||||||
|
|
||||||
// End of setup, test data
|
// End of setup, test data
|
||||||
|
|
||||||
commitAtH10 := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
commitAtH10 := &types.Commit{Precommits: []*types.UnsignedVote{{Height: 10,
|
||||||
Timestamp: tmtime.Now()}}}
|
Timestamp: tmtime.Now()}}}
|
||||||
tuples := []struct {
|
tuples := []struct {
|
||||||
block *types.Block
|
block *types.Block
|
||||||
@ -334,7 +334,7 @@ func TestBlockFetchAtHeight(t *testing.T) {
|
|||||||
block := makeBlock(bs.Height()+1, state)
|
block := makeBlock(bs.Height()+1, state)
|
||||||
|
|
||||||
partSet := block.MakePartSet(2)
|
partSet := block.MakePartSet(2)
|
||||||
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit := &types.Commit{Precommits: []*types.UnsignedVote{{Height: 10,
|
||||||
Timestamp: tmtime.Now()}}}
|
Timestamp: tmtime.Now()}}}
|
||||||
|
|
||||||
bs.SaveBlock(block, partSet, seenCommit)
|
bs.SaveBlock(block, partSet, seenCommit)
|
||||||
|
@ -70,8 +70,8 @@ func NewValidatorStub(privValidator types.PrivValidator, valIndex int) *validato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartSetHeader) (*types.Vote, error) {
|
func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartSetHeader) (*types.UnsignedVote, error) {
|
||||||
vote := &types.Vote{
|
vote := &types.UnsignedVote{
|
||||||
ValidatorIndex: vs.Index,
|
ValidatorIndex: vs.Index,
|
||||||
ValidatorAddress: vs.PrivValidator.GetAddress(),
|
ValidatorAddress: vs.PrivValidator.GetAddress(),
|
||||||
Height: vs.Height,
|
Height: vs.Height,
|
||||||
@ -85,7 +85,7 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sign vote for type/hash/header
|
// Sign vote for type/hash/header
|
||||||
func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSetHeader) *types.UnsignedVote {
|
||||||
v, err := vs.signVote(voteType, hash, header)
|
v, err := vs.signVote(voteType, hash, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to sign vote: %v", err))
|
panic(fmt.Errorf("failed to sign vote: %v", err))
|
||||||
@ -93,8 +93,8 @@ func signVote(vs *validatorStub, voteType byte, hash []byte, header types.PartSe
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.Vote {
|
func signVotes(voteType byte, hash []byte, header types.PartSetHeader, vss ...*validatorStub) []*types.UnsignedVote {
|
||||||
votes := make([]*types.Vote, len(vss))
|
votes := make([]*types.UnsignedVote, len(vss))
|
||||||
for i, vs := range vss {
|
for i, vs := range vss {
|
||||||
votes[i] = signVote(vs, voteType, hash, header)
|
votes[i] = signVote(vs, voteType, hash, header)
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ func decideProposal(cs1 *ConsensusState, vs *validatorStub, height int64, round
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addVotes(to *ConsensusState, votes ...*types.Vote) {
|
func addVotes(to *ConsensusState, votes ...*types.UnsignedVote) {
|
||||||
for _, vote := range votes {
|
for _, vote := range votes {
|
||||||
to.peerMsgQueue <- msgInfo{Msg: &VoteMessage{vote}}
|
to.peerMsgQueue <- msgInfo{Msg: &VoteMessage{vote}}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ func signAddVotes(to *ConsensusState, voteType byte, hash []byte, header types.P
|
|||||||
|
|
||||||
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
|
func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *validatorStub, blockHash []byte) {
|
||||||
prevotes := cs.Votes.Prevotes(round)
|
prevotes := cs.Votes.Prevotes(round)
|
||||||
var vote *types.Vote
|
var vote *types.UnsignedVote
|
||||||
if vote = prevotes.GetByAddress(privVal.GetAddress()); vote == nil {
|
if vote = prevotes.GetByAddress(privVal.GetAddress()); vote == nil {
|
||||||
panic("Failed to find prevote from validator")
|
panic("Failed to find prevote from validator")
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ func validatePrevote(t *testing.T, cs *ConsensusState, round int, privVal *valid
|
|||||||
|
|
||||||
func validateLastPrecommit(t *testing.T, cs *ConsensusState, privVal *validatorStub, blockHash []byte) {
|
func validateLastPrecommit(t *testing.T, cs *ConsensusState, privVal *validatorStub, blockHash []byte) {
|
||||||
votes := cs.LastCommit
|
votes := cs.LastCommit
|
||||||
var vote *types.Vote
|
var vote *types.UnsignedVote
|
||||||
if vote = votes.GetByAddress(privVal.GetAddress()); vote == nil {
|
if vote = votes.GetByAddress(privVal.GetAddress()); vote == nil {
|
||||||
panic("Failed to find precommit from validator")
|
panic("Failed to find precommit from validator")
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func validateLastPrecommit(t *testing.T, cs *ConsensusState, privVal *validatorS
|
|||||||
|
|
||||||
func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *validatorStub, votedBlockHash, lockedBlockHash []byte) {
|
func validatePrecommit(t *testing.T, cs *ConsensusState, thisRound, lockRound int, privVal *validatorStub, votedBlockHash, lockedBlockHash []byte) {
|
||||||
precommits := cs.Votes.Precommits(thisRound)
|
precommits := cs.Votes.Precommits(thisRound)
|
||||||
var vote *types.Vote
|
var vote *types.UnsignedVote
|
||||||
if vote = precommits.GetByAddress(privVal.GetAddress()); vote == nil {
|
if vote = precommits.GetByAddress(privVal.GetAddress()); vote == nil {
|
||||||
panic("Failed to find precommit from validator")
|
panic("Failed to find precommit from validator")
|
||||||
}
|
}
|
||||||
|
@ -359,7 +359,7 @@ func (conR *ConsensusReactor) subscribeToBroadcastEvents() {
|
|||||||
|
|
||||||
conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote,
|
conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote,
|
||||||
func(data tmevents.EventData) {
|
func(data tmevents.EventData) {
|
||||||
conR.broadcastHasVoteMessage(data.(*types.Vote))
|
conR.broadcastHasVoteMessage(data.(*types.UnsignedVote))
|
||||||
})
|
})
|
||||||
|
|
||||||
conR.conS.evsw.AddListenerForEvent(subscriber, types.EventProposalHeartbeat,
|
conR.conS.evsw.AddListenerForEvent(subscriber, types.EventProposalHeartbeat,
|
||||||
@ -391,7 +391,7 @@ func (conR *ConsensusReactor) broadcastNewRoundStepMessages(rs *cstypes.RoundSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Broadcasts HasVoteMessage to peers that care.
|
// Broadcasts HasVoteMessage to peers that care.
|
||||||
func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote) {
|
func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.UnsignedVote) {
|
||||||
msg := &HasVoteMessage{
|
msg := &HasVoteMessage{
|
||||||
Height: vote.Height,
|
Height: vote.Height,
|
||||||
Round: vote.Round,
|
Round: vote.Round,
|
||||||
@ -953,7 +953,7 @@ func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool {
|
|||||||
// PickVoteToSend picks a vote to send to the peer.
|
// PickVoteToSend picks a vote to send to the peer.
|
||||||
// Returns true if a vote was picked.
|
// Returns true if a vote was picked.
|
||||||
// NOTE: `votes` must be the correct Size() for the Height().
|
// NOTE: `votes` must be the correct Size() for the Height().
|
||||||
func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.Vote, ok bool) {
|
func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.UnsignedVote, ok bool) {
|
||||||
ps.mtx.Lock()
|
ps.mtx.Lock()
|
||||||
defer ps.mtx.Unlock()
|
defer ps.mtx.Unlock()
|
||||||
|
|
||||||
@ -1083,7 +1083,7 @@ func (ps *PeerState) ensureVoteBitArrays(height int64, numValidators int) {
|
|||||||
// RecordVote updates internal statistics for this peer by recording the vote.
|
// RecordVote updates internal statistics for this peer by recording the vote.
|
||||||
// It returns the total number of votes (1 per block). This essentially means
|
// It returns the total number of votes (1 per block). This essentially means
|
||||||
// the number of blocks for which peer has been sending us votes.
|
// the number of blocks for which peer has been sending us votes.
|
||||||
func (ps *PeerState) RecordVote(vote *types.Vote) int {
|
func (ps *PeerState) RecordVote(vote *types.UnsignedVote) int {
|
||||||
ps.mtx.Lock()
|
ps.mtx.Lock()
|
||||||
defer ps.mtx.Unlock()
|
defer ps.mtx.Unlock()
|
||||||
|
|
||||||
@ -1131,7 +1131,7 @@ func (ps *PeerState) BlockPartsSent() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetHasVote sets the given vote as known by the peer
|
// SetHasVote sets the given vote as known by the peer
|
||||||
func (ps *PeerState) SetHasVote(vote *types.Vote) {
|
func (ps *PeerState) SetHasVote(vote *types.UnsignedVote) {
|
||||||
ps.mtx.Lock()
|
ps.mtx.Lock()
|
||||||
defer ps.mtx.Unlock()
|
defer ps.mtx.Unlock()
|
||||||
|
|
||||||
@ -1299,7 +1299,7 @@ func RegisterConsensusMessages(cdc *amino.Codec) {
|
|||||||
cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil)
|
cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil)
|
||||||
cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil)
|
cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil)
|
||||||
cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil)
|
cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil)
|
||||||
cdc.RegisterConcrete(&VoteMessage{}, "tendermint/Vote", nil)
|
cdc.RegisterConcrete(&VoteMessage{}, "tendermint/UnsignedVote", nil)
|
||||||
cdc.RegisterConcrete(&HasVoteMessage{}, "tendermint/HasVote", nil)
|
cdc.RegisterConcrete(&HasVoteMessage{}, "tendermint/HasVote", nil)
|
||||||
cdc.RegisterConcrete(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23", nil)
|
cdc.RegisterConcrete(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23", nil)
|
||||||
cdc.RegisterConcrete(&VoteSetBitsMessage{}, "tendermint/VoteSetBits", nil)
|
cdc.RegisterConcrete(&VoteSetBitsMessage{}, "tendermint/VoteSetBits", nil)
|
||||||
@ -1390,12 +1390,12 @@ func (m *BlockPartMessage) String() string {
|
|||||||
|
|
||||||
// VoteMessage is sent when voting for a proposal (or lack thereof).
|
// VoteMessage is sent when voting for a proposal (or lack thereof).
|
||||||
type VoteMessage struct {
|
type VoteMessage struct {
|
||||||
Vote *types.Vote
|
Vote *types.UnsignedVote
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string representation.
|
// String returns a string representation.
|
||||||
func (m *VoteMessage) String() string {
|
func (m *VoteMessage) String() string {
|
||||||
return fmt.Sprintf("[Vote %v]", m.Vote)
|
return fmt.Sprintf("[UnsignedVote %v]", m.Vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
@ -317,7 +317,7 @@ func TestReactorRecordsVotes(t *testing.T) {
|
|||||||
_, val := css[0].state.Validators.GetByIndex(0)
|
_, val := css[0].state.Validators.GetByIndex(0)
|
||||||
|
|
||||||
// 1) new vote
|
// 1) new vote
|
||||||
vote := &types.Vote{
|
vote := &types.UnsignedVote{
|
||||||
ValidatorIndex: 0,
|
ValidatorIndex: 0,
|
||||||
ValidatorAddress: val.Address,
|
ValidatorAddress: val.Address,
|
||||||
Height: 2,
|
Height: 2,
|
||||||
|
@ -78,7 +78,7 @@ func (cs *ConsensusState) readReplayMessage(msg *TimedWALMessage, newStepCh chan
|
|||||||
cs.Logger.Info("Replay: BlockPart", "height", msg.Height, "round", msg.Round, "peer", peerID)
|
cs.Logger.Info("Replay: BlockPart", "height", msg.Height, "round", msg.Round, "peer", peerID)
|
||||||
case *VoteMessage:
|
case *VoteMessage:
|
||||||
v := msg.Vote
|
v := msg.Vote
|
||||||
cs.Logger.Info("Replay: Vote", "height", v.Height, "round", v.Round, "type", v.Type,
|
cs.Logger.Info("Replay: UnsignedVote", "height", v.Height, "round", v.Round, "type", v.Type,
|
||||||
"blockID", v.BlockID, "peer", peerID)
|
"blockID", v.BlockID, "peer", peerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,11 +541,11 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
case *types.Vote:
|
case *types.UnsignedVote:
|
||||||
if p.Type == types.VoteTypePrecommit {
|
if p.Type == types.VoteTypePrecommit {
|
||||||
thisBlockCommit = &types.Commit{
|
thisBlockCommit = &types.Commit{
|
||||||
BlockID: p.BlockID,
|
BlockID: p.BlockID,
|
||||||
Precommits: []*types.Vote{p},
|
Precommits: []*types.UnsignedVote{p},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ func (cs *ConsensusState) OpenWAL(walFile string) (WAL, error) {
|
|||||||
// TODO: should these return anything or let callers just use events?
|
// TODO: should these return anything or let callers just use events?
|
||||||
|
|
||||||
// AddVote inputs a vote.
|
// AddVote inputs a vote.
|
||||||
func (cs *ConsensusState) AddVote(vote *types.Vote, peerID p2p.ID) (added bool, err error) {
|
func (cs *ConsensusState) AddVote(vote *types.UnsignedVote, peerID p2p.ID) (added bool, err error) {
|
||||||
if peerID == "" {
|
if peerID == "" {
|
||||||
cs.internalMsgQueue <- msgInfo{&VoteMessage{vote}, ""}
|
cs.internalMsgQueue <- msgInfo{&VoteMessage{vote}, ""}
|
||||||
} else {
|
} else {
|
||||||
@ -961,7 +961,6 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
|
|||||||
return block, parts
|
return block, parts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Enter: `timeoutPropose` after entering Propose.
|
// Enter: `timeoutPropose` after entering Propose.
|
||||||
// Enter: proposal block and POL is ready.
|
// Enter: proposal block and POL is ready.
|
||||||
// Enter: any +2/3 prevotes for future round.
|
// Enter: any +2/3 prevotes for future round.
|
||||||
@ -1352,7 +1351,7 @@ func (cs *ConsensusState) recordMetrics(height int64, block *types.Block) {
|
|||||||
missingValidators := 0
|
missingValidators := 0
|
||||||
missingValidatorsPower := int64(0)
|
missingValidatorsPower := int64(0)
|
||||||
for i, val := range cs.Validators.Validators {
|
for i, val := range cs.Validators.Validators {
|
||||||
var vote *types.Vote
|
var vote *types.UnsignedVote
|
||||||
if i < len(block.LastCommit.Precommits) {
|
if i < len(block.LastCommit.Precommits) {
|
||||||
vote = block.LastCommit.Precommits[i]
|
vote = block.LastCommit.Precommits[i]
|
||||||
}
|
}
|
||||||
@ -1488,7 +1487,7 @@ func (cs *ConsensusState) addProposalBlockPart(msg *BlockPartMessage, peerID p2p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to add the vote. if its a duplicate signature, dupeout the validator
|
// Attempt to add the vote. if its a duplicate signature, dupeout the validator
|
||||||
func (cs *ConsensusState) tryAddVote(vote *types.Vote, peerID p2p.ID) error {
|
func (cs *ConsensusState) tryAddVote(vote *types.UnsignedVote, peerID p2p.ID) error {
|
||||||
_, err := cs.addVote(vote, peerID)
|
_, err := cs.addVote(vote, peerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the vote height is off, we'll just ignore it,
|
// If the vote height is off, we'll just ignore it,
|
||||||
@ -1515,7 +1514,7 @@ func (cs *ConsensusState) tryAddVote(vote *types.Vote, peerID p2p.ID) error {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error) {
|
func (cs *ConsensusState) addVote(vote *types.UnsignedVote, peerID p2p.ID) (added bool, err error) {
|
||||||
cs.Logger.Debug("addVote", "voteHeight", vote.Height, "voteType", vote.Type, "valIndex", vote.ValidatorIndex, "csHeight", cs.Height)
|
cs.Logger.Debug("addVote", "voteHeight", vote.Height, "voteType", vote.Type, "valIndex", vote.ValidatorIndex, "csHeight", cs.Height)
|
||||||
|
|
||||||
// A precommit for the previous height?
|
// A precommit for the previous height?
|
||||||
@ -1549,7 +1548,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
|||||||
// Not necessarily a bad peer, but not favourable behaviour.
|
// Not necessarily a bad peer, but not favourable behaviour.
|
||||||
if vote.Height != cs.Height {
|
if vote.Height != cs.Height {
|
||||||
err = ErrVoteHeightMismatch
|
err = ErrVoteHeightMismatch
|
||||||
cs.Logger.Info("Vote ignored and not added", "voteHeight", vote.Height, "csHeight", cs.Height, "err", err)
|
cs.Logger.Info("UnsignedVote ignored and not added", "voteHeight", vote.Height, "csHeight", cs.Height, "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1653,11 +1652,11 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSetHeader) (*types.Vote, error) {
|
func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSetHeader) (*types.UnsignedVote, error) {
|
||||||
addr := cs.privValidator.GetAddress()
|
addr := cs.privValidator.GetAddress()
|
||||||
valIndex, _ := cs.Validators.GetByAddress(addr)
|
valIndex, _ := cs.Validators.GetByAddress(addr)
|
||||||
|
|
||||||
vote := &types.Vote{
|
vote := &types.UnsignedVote{
|
||||||
ValidatorAddress: addr,
|
ValidatorAddress: addr,
|
||||||
ValidatorIndex: valIndex,
|
ValidatorIndex: valIndex,
|
||||||
Height: cs.Height,
|
Height: cs.Height,
|
||||||
@ -1688,7 +1687,7 @@ func (cs *ConsensusState) voteTime() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sign the vote and publish on internalMsgQueue
|
// sign the vote and publish on internalMsgQueue
|
||||||
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.UnsignedVote {
|
||||||
// if we don't have a key or we're not in the validator set, do nothing
|
// if we don't have a key or we're not in the validator set, do nothing
|
||||||
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.GetAddress()) {
|
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.GetAddress()) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -109,7 +109,7 @@ func (hvs *HeightVoteSet) addRound(round int) {
|
|||||||
|
|
||||||
// Duplicate votes return added=false, err=nil.
|
// Duplicate votes return added=false, err=nil.
|
||||||
// By convention, peerID is "" if origin is self.
|
// By convention, peerID is "" if origin is self.
|
||||||
func (hvs *HeightVoteSet) AddVote(vote *types.Vote, peerID p2p.ID) (added bool, err error) {
|
func (hvs *HeightVoteSet) AddVote(vote *types.UnsignedVote, peerID p2p.ID) (added bool, err error) {
|
||||||
hvs.mtx.Lock()
|
hvs.mtx.Lock()
|
||||||
defer hvs.mtx.Unlock()
|
defer hvs.mtx.Unlock()
|
||||||
if !types.IsVoteTypeValid(vote.Type) {
|
if !types.IsVoteTypeValid(vote.Type) {
|
||||||
|
@ -48,9 +48,9 @@ func TestPeerCatchupRounds(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivValidator, valIndex int) *types.Vote {
|
func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivValidator, valIndex int) *types.UnsignedVote {
|
||||||
privVal := privVals[valIndex]
|
privVal := privVals[valIndex]
|
||||||
vote := &types.Vote{
|
vote := &types.UnsignedVote{
|
||||||
ValidatorAddress: privVal.GetAddress(),
|
ValidatorAddress: privVal.GetAddress(),
|
||||||
ValidatorIndex: valIndex,
|
ValidatorIndex: valIndex,
|
||||||
Height: height,
|
Height: height,
|
||||||
|
@ -16,7 +16,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
|
|||||||
// Random validators
|
// Random validators
|
||||||
nval, ntxs := 100, 100
|
nval, ntxs := 100, 100
|
||||||
vset, _ := types.RandValidatorSet(nval, 1)
|
vset, _ := types.RandValidatorSet(nval, 1)
|
||||||
precommits := make([]*types.Vote, nval)
|
precommits := make([]*types.UnsignedVote, nval)
|
||||||
blockID := types.BlockID{
|
blockID := types.BlockID{
|
||||||
Hash: cmn.RandBytes(20),
|
Hash: cmn.RandBytes(20),
|
||||||
PartsHeader: types.PartSetHeader{
|
PartsHeader: types.PartSetHeader{
|
||||||
@ -25,7 +25,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
|
|||||||
}
|
}
|
||||||
sig := make([]byte, ed25519.SignatureSize)
|
sig := make([]byte, ed25519.SignatureSize)
|
||||||
for i := 0; i < nval; i++ {
|
for i := 0; i < nval; i++ {
|
||||||
precommits[i] = &types.Vote{
|
precommits[i] = &types.UnsignedVote{
|
||||||
ValidatorAddress: types.Address(cmn.RandBytes(20)),
|
ValidatorAddress: types.Address(cmn.RandBytes(20)),
|
||||||
Timestamp: tmtime.Now(),
|
Timestamp: tmtime.Now(),
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
|
@ -70,7 +70,7 @@ func (pkz privKeys) ToValidators(init, inc int64) *types.ValidatorSet {
|
|||||||
|
|
||||||
// signHeader properly signs the header with all keys from first to last exclusive.
|
// signHeader properly signs the header with all keys from first to last exclusive.
|
||||||
func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Commit {
|
func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Commit {
|
||||||
votes := make([]*types.Vote, len(pkz))
|
votes := make([]*types.UnsignedVote, len(pkz))
|
||||||
|
|
||||||
// We need this list to keep the ordering.
|
// We need this list to keep the ordering.
|
||||||
vset := pkz.ToValidators(1, 0)
|
vset := pkz.ToValidators(1, 0)
|
||||||
@ -88,10 +88,10 @@ func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Com
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVote(header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey) *types.Vote {
|
func makeVote(header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey) *types.UnsignedVote {
|
||||||
addr := key.PubKey().Address()
|
addr := key.PubKey().Address()
|
||||||
idx, _ := valset.GetByAddress(addr)
|
idx, _ := valset.GetByAddress(addr)
|
||||||
vote := &types.Vote{
|
vote := &types.UnsignedVote{
|
||||||
ValidatorAddress: addr,
|
ValidatorAddress: addr,
|
||||||
ValidatorIndex: idx,
|
ValidatorIndex: idx,
|
||||||
Height: header.Height,
|
Height: header.Height,
|
||||||
|
@ -23,7 +23,7 @@ const (
|
|||||||
stepPrecommit int8 = 3
|
stepPrecommit int8 = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
func voteToStep(vote *types.Vote) int8 {
|
func voteToStep(vote *types.UnsignedVote) int8 {
|
||||||
switch vote.Type {
|
switch vote.Type {
|
||||||
case types.VoteTypePrevote:
|
case types.VoteTypePrevote:
|
||||||
return stepPrevote
|
return stepPrevote
|
||||||
@ -150,7 +150,7 @@ func (pv *FilePV) Reset() {
|
|||||||
|
|
||||||
// SignVote signs a canonical representation of the vote, along with the
|
// SignVote signs a canonical representation of the vote, along with the
|
||||||
// chainID. Implements PrivValidator.
|
// chainID. Implements PrivValidator.
|
||||||
func (pv *FilePV) SignVote(chainID string, vote *types.Vote) error {
|
func (pv *FilePV) SignVote(chainID string, vote *types.UnsignedVote) error {
|
||||||
pv.mtx.Lock()
|
pv.mtx.Lock()
|
||||||
defer pv.mtx.Unlock()
|
defer pv.mtx.Unlock()
|
||||||
if err := pv.signVote(chainID, vote); err != nil {
|
if err := pv.signVote(chainID, vote); err != nil {
|
||||||
@ -201,7 +201,7 @@ func (pv *FilePV) checkHRS(height int64, round int, step int8) (bool, error) {
|
|||||||
// signVote checks if the vote is good to sign and sets the vote signature.
|
// signVote checks if the vote is good to sign and sets the vote signature.
|
||||||
// It may need to set the timestamp as well if the vote is otherwise the same as
|
// It may need to set the timestamp as well if the vote is otherwise the same as
|
||||||
// a previously signed vote (ie. we crashed after signing but before the vote hit the WAL).
|
// a previously signed vote (ie. we crashed after signing but before the vote hit the WAL).
|
||||||
func (pv *FilePV) signVote(chainID string, vote *types.Vote) error {
|
func (pv *FilePV) signVote(chainID string, vote *types.UnsignedVote) error {
|
||||||
height, round, step := vote.Height, vote.Round, voteToStep(vote)
|
height, round, step := vote.Height, vote.Round, voteToStep(vote)
|
||||||
signBytes := vote.SignBytes(chainID)
|
signBytes := vote.SignBytes(chainID)
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func TestSignVote(t *testing.T) {
|
|||||||
assert.NoError(err, "expected no error on signing same vote")
|
assert.NoError(err, "expected no error on signing same vote")
|
||||||
|
|
||||||
// now try some bad votes
|
// now try some bad votes
|
||||||
cases := []*types.Vote{
|
cases := []*types.UnsignedVote{
|
||||||
newVote(privVal.Address, 0, height, round-1, voteType, block1), // round regression
|
newVote(privVal.Address, 0, height, round-1, voteType, block1), // round regression
|
||||||
newVote(privVal.Address, 0, height-1, round, voteType, block1), // height regression
|
newVote(privVal.Address, 0, height-1, round, voteType, block1), // height regression
|
||||||
newVote(privVal.Address, 0, height-2, round+4, voteType, block1), // height regression and different round
|
newVote(privVal.Address, 0, height-2, round+4, voteType, block1), // height regression and different round
|
||||||
@ -229,8 +229,8 @@ func TestDifferByTimestamp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVote(addr types.Address, idx int, height int64, round int, typ byte, blockID types.BlockID) *types.Vote {
|
func newVote(addr types.Address, idx int, height int64, round int, typ byte, blockID types.BlockID) *types.UnsignedVote {
|
||||||
return &types.Vote{
|
return &types.UnsignedVote{
|
||||||
ValidatorAddress: addr,
|
ValidatorAddress: addr,
|
||||||
ValidatorIndex: idx,
|
ValidatorIndex: idx,
|
||||||
Height: height,
|
Height: height,
|
||||||
|
@ -149,8 +149,8 @@ func (sc *SocketPV) getPubKey() (crypto.PubKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SignVote implements PrivValidator.
|
// SignVote implements PrivValidator.
|
||||||
func (sc *SocketPV) SignVote(chainID string, vote *types.Vote) error {
|
func (sc *SocketPV) SignVote(chainID string, vote *types.UnsignedVote) (*types.SignedVote, error) {
|
||||||
err := writeMsg(sc.conn, &SignVoteMsg{Vote: vote})
|
err := writeMsg(sc.conn, &SignVoteRequest{Vote: vote})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ func (sc *SocketPV) SignVote(chainID string, vote *types.Vote) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*vote = *res.(*SignVoteMsg).Vote
|
*vote = *res.(*SignVoteRequest).Vote
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -462,9 +462,9 @@ func (rs *RemoteSigner) handleConnection(conn net.Conn) {
|
|||||||
var p crypto.PubKey
|
var p crypto.PubKey
|
||||||
p = rs.privVal.GetPubKey()
|
p = rs.privVal.GetPubKey()
|
||||||
res = &PubKeyMsg{p}
|
res = &PubKeyMsg{p}
|
||||||
case *SignVoteMsg:
|
case *SignVoteRequest:
|
||||||
err = rs.privVal.SignVote(rs.chainID, r.Vote)
|
err = rs.privVal.SignVote(rs.chainID, r.Vote)
|
||||||
res = &SignVoteMsg{r.Vote}
|
res = &SignVoteRequest{r.Vote}
|
||||||
case *SignProposalMsg:
|
case *SignProposalMsg:
|
||||||
err = rs.privVal.SignProposal(rs.chainID, r.Proposal)
|
err = rs.privVal.SignProposal(rs.chainID, r.Proposal)
|
||||||
res = &SignProposalMsg{r.Proposal}
|
res = &SignProposalMsg{r.Proposal}
|
||||||
@ -496,7 +496,8 @@ type SocketPVMsg interface{}
|
|||||||
func RegisterSocketPVMsg(cdc *amino.Codec) {
|
func RegisterSocketPVMsg(cdc *amino.Codec) {
|
||||||
cdc.RegisterInterface((*SocketPVMsg)(nil), nil)
|
cdc.RegisterInterface((*SocketPVMsg)(nil), nil)
|
||||||
cdc.RegisterConcrete(&PubKeyMsg{}, "tendermint/socketpv/PubKeyMsg", nil)
|
cdc.RegisterConcrete(&PubKeyMsg{}, "tendermint/socketpv/PubKeyMsg", nil)
|
||||||
cdc.RegisterConcrete(&SignVoteMsg{}, "tendermint/socketpv/SignVoteMsg", nil)
|
cdc.RegisterConcrete(&SignVoteRequest{}, "tendermint/socketpv/SignVoteRequest", nil)
|
||||||
|
cdc.RegisterConcrete(&SignedVoteReply{}, "tendermint/socketpv/SignVoteReply", nil)
|
||||||
cdc.RegisterConcrete(&SignProposalMsg{}, "tendermint/socketpv/SignProposalMsg", nil)
|
cdc.RegisterConcrete(&SignProposalMsg{}, "tendermint/socketpv/SignProposalMsg", nil)
|
||||||
cdc.RegisterConcrete(&SignHeartbeatMsg{}, "tendermint/socketpv/SignHeartbeatMsg", nil)
|
cdc.RegisterConcrete(&SignHeartbeatMsg{}, "tendermint/socketpv/SignHeartbeatMsg", nil)
|
||||||
}
|
}
|
||||||
@ -506,9 +507,16 @@ type PubKeyMsg struct {
|
|||||||
PubKey crypto.PubKey
|
PubKey crypto.PubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignVoteMsg is a PrivValidatorSocket message containing a vote.
|
// SignVoteRequest is a PrivValidatorSocket message containing a vote.
|
||||||
type SignVoteMsg struct {
|
type SignVoteRequest struct {
|
||||||
Vote *types.Vote
|
Vote *types.UnsignedVote
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignVoteReply is a PrivValidatorSocket message containing a signed vote and potential
|
||||||
|
// errors returned by the (remote) signer.
|
||||||
|
type SignedVoteReply struct {
|
||||||
|
Vote *types.SignedVote
|
||||||
|
Error *types.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignProposalMsg is a PrivValidatorSocket message containing a Proposal.
|
// SignProposalMsg is a PrivValidatorSocket message containing a Proposal.
|
||||||
|
@ -80,8 +80,8 @@ func TestSocketPVVote(t *testing.T) {
|
|||||||
|
|
||||||
ts = time.Now()
|
ts = time.Now()
|
||||||
vType = types.VoteTypePrecommit
|
vType = types.VoteTypePrecommit
|
||||||
want = &types.Vote{Timestamp: ts, Type: vType}
|
want = &types.UnsignedVote{Timestamp: ts, Type: vType}
|
||||||
have = &types.Vote{Timestamp: ts, Type: vType}
|
have = &types.UnsignedVote{Timestamp: ts, Type: vType}
|
||||||
)
|
)
|
||||||
defer sc.Stop()
|
defer sc.Stop()
|
||||||
defer rs.Stop()
|
defer rs.Stop()
|
||||||
|
@ -125,7 +125,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
|
|||||||
// "commit_round": -1,
|
// "commit_round": -1,
|
||||||
// "last_commit": {
|
// "last_commit": {
|
||||||
// "votes": [
|
// "votes": [
|
||||||
// "Vote{0:B5B3D40BE539 7184/00/2(Precommit) 14F946FA7EF0 /702B1B1A602A.../ @ 2018-05-12T20:57:27.342Z}"
|
// "UnsignedVote{0:B5B3D40BE539 7184/00/2(Precommit) 14F946FA7EF0 /702B1B1A602A.../ @ 2018-05-12T20:57:27.342Z}"
|
||||||
// ],
|
// ],
|
||||||
// "votes_bit_array": "x",
|
// "votes_bit_array": "x",
|
||||||
// "peer_maj_23s": {}
|
// "peer_maj_23s": {}
|
||||||
@ -243,11 +243,11 @@ func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
|
|||||||
// {
|
// {
|
||||||
// "round": 0,
|
// "round": 0,
|
||||||
// "prevotes": [
|
// "prevotes": [
|
||||||
// "nil-Vote"
|
// "nil-UnsignedVote"
|
||||||
// ],
|
// ],
|
||||||
// "prevotes_bit_array": "BA{1:_} 0/10 = 0.00",
|
// "prevotes_bit_array": "BA{1:_} 0/10 = 0.00",
|
||||||
// "precommits": [
|
// "precommits": [
|
||||||
// "nil-Vote"
|
// "nil-UnsignedVote"
|
||||||
// ],
|
// ],
|
||||||
// "precommits_bit_array": "BA{1:_} 0/10 = 0.00"
|
// "precommits_bit_array": "BA{1:_} 0/10 = 0.00"
|
||||||
// }
|
// }
|
||||||
|
@ -246,7 +246,7 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS
|
|||||||
// Collect the vote info (list of validators and whether or not they signed).
|
// Collect the vote info (list of validators and whether or not they signed).
|
||||||
voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
|
voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
|
||||||
for i, val := range lastValSet.Validators {
|
for i, val := range lastValSet.Validators {
|
||||||
var vote *types.Vote
|
var vote *types.UnsignedVote
|
||||||
if i < len(block.LastCommit.Precommits) {
|
if i < len(block.LastCommit.Precommits) {
|
||||||
vote = block.LastCommit.Precommits[i]
|
vote = block.LastCommit.Precommits[i]
|
||||||
}
|
}
|
||||||
|
@ -64,17 +64,17 @@ func TestBeginBlockValidators(t *testing.T) {
|
|||||||
prevBlockID := types.BlockID{prevHash, prevParts}
|
prevBlockID := types.BlockID{prevHash, prevParts}
|
||||||
|
|
||||||
now := tmtime.Now()
|
now := tmtime.Now()
|
||||||
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
vote0 := &types.UnsignedVote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
||||||
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
|
vote1 := &types.UnsignedVote{ValidatorIndex: 1, Timestamp: now}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
lastCommitPrecommits []*types.Vote
|
lastCommitPrecommits []*types.UnsignedVote
|
||||||
expectedAbsentValidators []int
|
expectedAbsentValidators []int
|
||||||
}{
|
}{
|
||||||
{"none absent", []*types.Vote{vote0, vote1}, []int{}},
|
{"none absent", []*types.UnsignedVote{vote0, vote1}, []int{}},
|
||||||
{"one absent", []*types.Vote{vote0, nil}, []int{1}},
|
{"one absent", []*types.UnsignedVote{vote0, nil}, []int{1}},
|
||||||
{"multiple absent", []*types.Vote{nil, nil}, []int{0, 1}},
|
{"multiple absent", []*types.UnsignedVote{nil, nil}, []int{0, 1}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@ -135,9 +135,9 @@ func TestBeginBlockByzantineValidators(t *testing.T) {
|
|||||||
types.TM2PB.Evidence(ev2, valSet, now)}},
|
types.TM2PB.Evidence(ev2, valSet, now)}},
|
||||||
}
|
}
|
||||||
|
|
||||||
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
vote0 := &types.UnsignedVote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
||||||
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
|
vote1 := &types.UnsignedVote{ValidatorIndex: 1, Timestamp: now}
|
||||||
votes := []*types.Vote{vote0, vote1}
|
votes := []*types.UnsignedVote{vote0, vote1}
|
||||||
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
|
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
||||||
|
@ -332,18 +332,18 @@ type Commit struct {
|
|||||||
// NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
|
// NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
|
||||||
// Any peer with a block can gossip precommits by index with a peer without recalculating the
|
// Any peer with a block can gossip precommits by index with a peer without recalculating the
|
||||||
// active ValidatorSet.
|
// active ValidatorSet.
|
||||||
BlockID BlockID `json:"block_id"`
|
BlockID BlockID `json:"block_id"`
|
||||||
Precommits []*Vote `json:"precommits"`
|
Precommits []*SignedVote `json:"precommits"`
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
firstPrecommit *Vote
|
firstPrecommit *SignedVote
|
||||||
hash cmn.HexBytes
|
hash cmn.HexBytes
|
||||||
bitArray *cmn.BitArray
|
bitArray *cmn.BitArray
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstPrecommit returns the first non-nil precommit in the commit.
|
// FirstPrecommit returns the first non-nil precommit in the commit.
|
||||||
// If all precommits are nil, it returns an empty precommit with height 0.
|
// If all precommits are nil, it returns an empty precommit with height 0.
|
||||||
func (commit *Commit) FirstPrecommit() *Vote {
|
func (commit *Commit) FirstPrecommit() *SignedVote {
|
||||||
if len(commit.Precommits) == 0 {
|
if len(commit.Precommits) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -356,8 +356,12 @@ func (commit *Commit) FirstPrecommit() *Vote {
|
|||||||
return precommit
|
return precommit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Vote{
|
return &SignedVote{
|
||||||
Type: VoteTypePrecommit,
|
// TODO(ismail): That is confusing; does the caller expect a signed pre-commit or not?
|
||||||
|
// looks like this is always unsigned (check how this is reflected in the spec)
|
||||||
|
Vote: &UnsignedVote{
|
||||||
|
Type: VoteTypePrecommit,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +370,7 @@ func (commit *Commit) Height() int64 {
|
|||||||
if len(commit.Precommits) == 0 {
|
if len(commit.Precommits) == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return commit.FirstPrecommit().Height
|
return commit.FirstPrecommit().Vote.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round returns the round of the commit
|
// Round returns the round of the commit
|
||||||
@ -374,7 +378,7 @@ func (commit *Commit) Round() int {
|
|||||||
if len(commit.Precommits) == 0 {
|
if len(commit.Precommits) == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return commit.FirstPrecommit().Round
|
return commit.FirstPrecommit().Vote.Round
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the vote type of the commit, which is always VoteTypePrecommit
|
// Type returns the vote type of the commit, which is always VoteTypePrecommit
|
||||||
@ -404,7 +408,7 @@ func (commit *Commit) BitArray() *cmn.BitArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetByIndex returns the vote corresponding to a given validator index
|
// GetByIndex returns the vote corresponding to a given validator index
|
||||||
func (commit *Commit) GetByIndex(index int) *Vote {
|
func (commit *Commit) GetByIndex(index int) *SignedVote {
|
||||||
return commit.Precommits[index]
|
return commit.Precommits[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,23 +431,23 @@ func (commit *Commit) ValidateBasic() error {
|
|||||||
// Validate the precommits.
|
// Validate the precommits.
|
||||||
for _, precommit := range commit.Precommits {
|
for _, precommit := range commit.Precommits {
|
||||||
// It's OK for precommits to be missing.
|
// It's OK for precommits to be missing.
|
||||||
if precommit == nil {
|
if precommit == nil || precommit.Vote == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Ensure that all votes are precommits.
|
// Ensure that all votes are precommits.
|
||||||
if precommit.Type != VoteTypePrecommit {
|
if precommit.Vote.Type != VoteTypePrecommit {
|
||||||
return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
|
return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
|
||||||
precommit.Type)
|
precommit.Vote.Type)
|
||||||
}
|
}
|
||||||
// Ensure that all heights are the same.
|
// Ensure that all heights are the same.
|
||||||
if precommit.Height != height {
|
if precommit.Vote.Height != height {
|
||||||
return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
|
return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
|
||||||
height, precommit.Height)
|
height, precommit.Vote.Height)
|
||||||
}
|
}
|
||||||
// Ensure that all rounds are the same.
|
// Ensure that all rounds are the same.
|
||||||
if precommit.Round != round {
|
if precommit.Vote.Round != round {
|
||||||
return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
|
return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
|
||||||
round, precommit.Round)
|
round, precommit.Vote.Round)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -471,7 +475,7 @@ func (commit *Commit) StringIndented(indent string) string {
|
|||||||
}
|
}
|
||||||
precommitStrings := make([]string, len(commit.Precommits))
|
precommitStrings := make([]string, len(commit.Precommits))
|
||||||
for i, precommit := range commit.Precommits {
|
for i, precommit := range commit.Precommits {
|
||||||
precommitStrings[i] = precommit.String()
|
precommitStrings[i] = precommit.Vote.String()
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`Commit{
|
return fmt.Sprintf(`Commit{
|
||||||
%s BlockID: %v
|
%s BlockID: %v
|
||||||
|
@ -221,17 +221,17 @@ func TestCommitValidateBasic(t *testing.T) {
|
|||||||
|
|
||||||
// tamper with types
|
// tamper with types
|
||||||
commit = randCommit()
|
commit = randCommit()
|
||||||
commit.Precommits[0].Type = VoteTypePrevote
|
commit.Precommits[0].Vote.Type = VoteTypePrevote
|
||||||
assert.Error(t, commit.ValidateBasic())
|
assert.Error(t, commit.ValidateBasic())
|
||||||
|
|
||||||
// tamper with height
|
// tamper with height
|
||||||
commit = randCommit()
|
commit = randCommit()
|
||||||
commit.Precommits[0].Height = int64(100)
|
commit.Precommits[0].Vote.Height = int64(100)
|
||||||
assert.Error(t, commit.ValidateBasic())
|
assert.Error(t, commit.ValidateBasic())
|
||||||
|
|
||||||
// tamper with round
|
// tamper with round
|
||||||
commit = randCommit()
|
commit = randCommit()
|
||||||
commit.Precommits[0].Round = 100
|
commit.Precommits[0].Vote.Round = 100
|
||||||
assert.Error(t, commit.ValidateBasic())
|
assert.Error(t, commit.ValidateBasic())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ const (
|
|||||||
EventTx = "Tx"
|
EventTx = "Tx"
|
||||||
EventUnlock = "Unlock"
|
EventUnlock = "Unlock"
|
||||||
EventValidatorSetUpdates = "ValidatorSetUpdates"
|
EventValidatorSetUpdates = "ValidatorSetUpdates"
|
||||||
EventVote = "Vote"
|
EventVote = "UnsignedVote"
|
||||||
)
|
)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -42,7 +42,7 @@ func RegisterEventDatas(cdc *amino.Codec) {
|
|||||||
cdc.RegisterConcrete(EventDataNewBlockHeader{}, "tendermint/event/NewBlockHeader", nil)
|
cdc.RegisterConcrete(EventDataNewBlockHeader{}, "tendermint/event/NewBlockHeader", nil)
|
||||||
cdc.RegisterConcrete(EventDataTx{}, "tendermint/event/Tx", nil)
|
cdc.RegisterConcrete(EventDataTx{}, "tendermint/event/Tx", nil)
|
||||||
cdc.RegisterConcrete(EventDataRoundState{}, "tendermint/event/RoundState", nil)
|
cdc.RegisterConcrete(EventDataRoundState{}, "tendermint/event/RoundState", nil)
|
||||||
cdc.RegisterConcrete(EventDataVote{}, "tendermint/event/Vote", nil)
|
cdc.RegisterConcrete(EventDataVote{}, "tendermint/event/UnsignedVote", nil)
|
||||||
cdc.RegisterConcrete(EventDataProposalHeartbeat{}, "tendermint/event/ProposalHeartbeat", nil)
|
cdc.RegisterConcrete(EventDataProposalHeartbeat{}, "tendermint/event/ProposalHeartbeat", nil)
|
||||||
cdc.RegisterConcrete(EventDataValidatorSetUpdates{}, "tendermint/event/ValidatorSetUpdates", nil)
|
cdc.RegisterConcrete(EventDataValidatorSetUpdates{}, "tendermint/event/ValidatorSetUpdates", nil)
|
||||||
cdc.RegisterConcrete(EventDataString(""), "tendermint/event/ProposalString", nil)
|
cdc.RegisterConcrete(EventDataString(""), "tendermint/event/ProposalString", nil)
|
||||||
@ -80,7 +80,7 @@ type EventDataRoundState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EventDataVote struct {
|
type EventDataVote struct {
|
||||||
Vote *Vote
|
Vote *UnsignedVote
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventDataString string
|
type EventDataString string
|
||||||
|
@ -34,11 +34,11 @@ func (err *ErrEvidenceInvalid) Error() string {
|
|||||||
|
|
||||||
// Evidence represents any provable malicious activity by a validator
|
// Evidence represents any provable malicious activity by a validator
|
||||||
type Evidence interface {
|
type Evidence interface {
|
||||||
Height() int64 // height of the equivocation
|
Height() int64 // height of the equivocation
|
||||||
Address() []byte // address of the equivocating validator
|
Address() []byte // address of the equivocating validator
|
||||||
Hash() []byte // hash of the evidence
|
Hash() []byte // hash of the evidence
|
||||||
Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence
|
Verify(pubKey crypto.PubKey) error // verify the evidence
|
||||||
Equal(Evidence) bool // check equality of evidence
|
Equal(Evidence) bool // check equality of evidence
|
||||||
|
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
@ -63,8 +63,8 @@ func MaxEvidenceBytesPerBlock(blockMaxBytes int) int {
|
|||||||
type DuplicateVoteEvidence struct {
|
type DuplicateVoteEvidence struct {
|
||||||
PubKey crypto.PubKey
|
PubKey crypto.PubKey
|
||||||
// TODO(ismail): this probably need to be `SignedVoteReply`s
|
// TODO(ismail): this probably need to be `SignedVoteReply`s
|
||||||
VoteA *SignVoteReply
|
VoteA *SignedVote
|
||||||
VoteB *SignVoteReply
|
VoteB *SignedVote
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string representation of the evidence.
|
// String returns a string representation of the evidence.
|
||||||
@ -90,7 +90,7 @@ func (dve *DuplicateVoteEvidence) Hash() []byte {
|
|||||||
|
|
||||||
// Verify returns an error if the two votes aren't conflicting.
|
// Verify returns an error if the two votes aren't conflicting.
|
||||||
// To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks.
|
// To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks.
|
||||||
func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
|
func (dve *DuplicateVoteEvidence) Verify(pubKey crypto.PubKey) error {
|
||||||
// H/R/S must be the same
|
// H/R/S must be the same
|
||||||
if dve.VoteA.Vote.Height != dve.VoteB.Vote.Height ||
|
if dve.VoteA.Vote.Height != dve.VoteB.Vote.Height ||
|
||||||
dve.VoteA.Vote.Round != dve.VoteB.Vote.Round ||
|
dve.VoteA.Vote.Round != dve.VoteB.Vote.Round ||
|
||||||
@ -161,7 +161,7 @@ func (e MockGoodEvidence) Address() []byte { return e.Address_ }
|
|||||||
func (e MockGoodEvidence) Hash() []byte {
|
func (e MockGoodEvidence) Hash() []byte {
|
||||||
return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
|
return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
|
||||||
}
|
}
|
||||||
func (e MockGoodEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil }
|
func (e MockGoodEvidence) Verify(pubKey crypto.PubKey) error { return nil }
|
||||||
func (e MockGoodEvidence) Equal(ev Evidence) bool {
|
func (e MockGoodEvidence) Equal(ev Evidence) bool {
|
||||||
e2 := ev.(MockGoodEvidence)
|
e2 := ev.(MockGoodEvidence)
|
||||||
return e.Height_ == e2.Height_ &&
|
return e.Height_ == e2.Height_ &&
|
||||||
@ -176,7 +176,7 @@ type MockBadEvidence struct {
|
|||||||
MockGoodEvidence
|
MockGoodEvidence
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e MockBadEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
|
func (e MockBadEvidence) Verify(pubKey crypto.PubKey) error {
|
||||||
return fmt.Errorf("MockBadEvidence")
|
return fmt.Errorf("MockBadEvidence")
|
||||||
}
|
}
|
||||||
func (e MockBadEvidence) Equal(ev Evidence) bool {
|
func (e MockBadEvidence) Equal(ev Evidence) bool {
|
||||||
|
@ -11,25 +11,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type voteData struct {
|
type voteData struct {
|
||||||
vote1 *Vote
|
vote1 *SignedVote
|
||||||
vote2 *Vote
|
vote2 *SignedVote
|
||||||
valid bool
|
valid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVote(val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID) *Vote {
|
func makeVote(val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID) *SignedVote {
|
||||||
v := &Vote{
|
v := &UnsignedVote{
|
||||||
ValidatorAddress: val.GetAddress(),
|
ValidatorAddress: val.GetAddress(),
|
||||||
ValidatorIndex: valIndex,
|
ValidatorIndex: valIndex,
|
||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
||||||
Type: byte(step),
|
Type: byte(step),
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
|
ChainID: chainID,
|
||||||
}
|
}
|
||||||
err := val.SignVote(chainID, v)
|
sv, err := val.SignVote(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return v
|
return sv
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEvidence(t *testing.T) {
|
func TestEvidence(t *testing.T) {
|
||||||
@ -45,7 +46,7 @@ func TestEvidence(t *testing.T) {
|
|||||||
|
|
||||||
vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID)
|
vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID)
|
||||||
badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID)
|
badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID)
|
||||||
err := val2.SignVote(chainID, badVote)
|
signedBadVote, err := val2.SignVote(badVote.Vote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -61,19 +62,21 @@ func TestEvidence(t *testing.T) {
|
|||||||
{vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
|
{vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
|
||||||
{vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
|
{vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
|
||||||
{vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
|
{vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
|
||||||
{vote1, badVote, false}, // signed by wrong key
|
{vote1, signedBadVote, false}, // signed by wrong key
|
||||||
}
|
}
|
||||||
|
|
||||||
pubKey := val.GetPubKey()
|
pubKey := val.GetPubKey()
|
||||||
for _, c := range cases {
|
for idx, c := range cases {
|
||||||
|
//fmt.Println(idx)
|
||||||
ev := &DuplicateVoteEvidence{
|
ev := &DuplicateVoteEvidence{
|
||||||
VoteA: c.vote1,
|
VoteA: c.vote1,
|
||||||
VoteB: c.vote2,
|
VoteB: c.vote2,
|
||||||
}
|
}
|
||||||
if c.valid {
|
if c.valid {
|
||||||
assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
|
assert.NoError(t, ev.Verify(pubKey), "evidence should be valid")
|
||||||
} else {
|
} else {
|
||||||
assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
|
t.Logf("idx=%v, err=%s", idx, ev.Verify(pubKey))
|
||||||
|
assert.Error(t, ev.Verify(pubKey), "evidence should be invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ type PrivValidator interface {
|
|||||||
GetAddress() Address // redundant since .PubKey().Address()
|
GetAddress() Address // redundant since .PubKey().Address()
|
||||||
GetPubKey() crypto.PubKey
|
GetPubKey() crypto.PubKey
|
||||||
|
|
||||||
SignVote(vote *Vote) (SignVoteReply, error)
|
SignVote(vote *UnsignedVote) (*SignedVote, error)
|
||||||
SignProposal(chainID string, proposal *Proposal) error
|
SignProposal(chainID string, proposal *Proposal) error
|
||||||
SignHeartbeat(chainID string, heartbeat *Heartbeat) error
|
SignHeartbeat(chainID string, heartbeat *Heartbeat) error
|
||||||
}
|
}
|
||||||
@ -62,16 +62,15 @@ func (pv *MockPV) GetPubKey() crypto.PubKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements PrivValidator.
|
// Implements PrivValidator.
|
||||||
func (pv *MockPV) SignVote(vote *Vote) (SignVoteReply, error) {
|
func (pv *MockPV) SignVote(vote *UnsignedVote) (*SignedVote, error) {
|
||||||
signBytes := vote.SignBytes()
|
signBytes := vote.SignBytes()
|
||||||
sig, err := pv.privKey.Sign(signBytes)
|
sig, err := pv.privKey.Sign(signBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(ismail): encapsulate error into reply!
|
return nil, err
|
||||||
return SignVoteReply{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SignVoteReply{
|
return &SignedVote{
|
||||||
Vote: *vote,
|
Vote: vote,
|
||||||
Signature: sig,
|
Signature: sig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ func MakeCommit(blockID BlockID, height int64, round int,
|
|||||||
// all sign
|
// all sign
|
||||||
for i := 0; i < len(validators); i++ {
|
for i := 0; i < len(validators); i++ {
|
||||||
|
|
||||||
vote := &Vote{
|
vote := &UnsignedVote{
|
||||||
ValidatorAddress: validators[i].GetAddress(),
|
ValidatorAddress: validators[i].GetAddress(),
|
||||||
ValidatorIndex: i,
|
ValidatorIndex: i,
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -30,11 +30,11 @@ func MakeCommit(blockID BlockID, height int64, round int,
|
|||||||
return voteSet.MakeCommit(), nil
|
return voteSet.MakeCommit(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) {
|
func signAddVote(privVal PrivValidator, vote *UnsignedVote, voteSet *VoteSet) (signed bool, err error) {
|
||||||
vote.ChainID = voteSet.ChainID()
|
vote.ChainID = voteSet.ChainID()
|
||||||
repl, err := privVal.SignVote(vote)
|
repl, err := privVal.SignVote(vote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return voteSet.AddVote(vote)
|
return voteSet.AddVote(repl)
|
||||||
}
|
}
|
||||||
|
@ -273,26 +273,31 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
|
|||||||
round := commit.Round()
|
round := commit.Round()
|
||||||
|
|
||||||
for idx, precommit := range commit.Precommits {
|
for idx, precommit := range commit.Precommits {
|
||||||
if precommit == nil {
|
if precommit == nil || precommit.Vote == nil {
|
||||||
continue // OK, some precommits can be missing.
|
continue // OK, some precommits can be missing.
|
||||||
}
|
}
|
||||||
if precommit.Height != height {
|
if precommit.Vote.Height != height {
|
||||||
return fmt.Errorf("Invalid commit -- wrong height: want %v got %v", height, precommit.Height)
|
return fmt.Errorf("invalid commit -- wrong height: want %v got %v", height, precommit.Vote.Height)
|
||||||
}
|
}
|
||||||
if precommit.Round != round {
|
if precommit.Vote.Round != round {
|
||||||
return fmt.Errorf("Invalid commit -- wrong round: want %v got %v", round, precommit.Round)
|
return fmt.Errorf("invalid commit -- wrong round: want %v got %v", round, precommit.Vote.Round)
|
||||||
}
|
}
|
||||||
if precommit.Type != VoteTypePrecommit {
|
if precommit.Vote.Type != VoteTypePrecommit {
|
||||||
return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx)
|
return fmt.Errorf("invalid commit -- not precommit @ index %v", idx)
|
||||||
}
|
}
|
||||||
_, val := vals.GetByIndex(idx)
|
_, val := vals.GetByIndex(idx)
|
||||||
// Validate signature.
|
// Validate signature.
|
||||||
precommitSignBytes := precommit.SignBytes()
|
precommitSignBytes := precommit.Vote.SignBytes()
|
||||||
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 precommit.Vote.ChainID != chainID {
|
||||||
|
return fmt.Errorf("invalid commit -- chainId does not match: expected %v, got %v", chainID, precommit.Vote.ChainID)
|
||||||
|
}
|
||||||
|
|
||||||
// Good precommit!
|
// Good precommit!
|
||||||
if blockID.Equals(precommit.BlockID) {
|
if blockID.Equals(precommit.Vote.BlockID) {
|
||||||
talliedVotingPower += val.VotingPower
|
talliedVotingPower += val.VotingPower
|
||||||
} else {
|
} else {
|
||||||
// It's OK that the BlockID doesn't match. We include stray
|
// It's OK that the BlockID doesn't match. We include stray
|
||||||
@ -303,7 +308,7 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
|
|||||||
if talliedVotingPower > vals.TotalVotingPower()*2/3 {
|
if talliedVotingPower > vals.TotalVotingPower()*2/3 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Invalid commit -- insufficient voting power: got %v, needed %v",
|
return fmt.Errorf("invalid commit -- insufficient voting power: got %v, needed %v",
|
||||||
talliedVotingPower, (vals.TotalVotingPower()*2/3 + 1))
|
talliedVotingPower, (vals.TotalVotingPower()*2/3 + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,32 +357,32 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
|
|||||||
round := commit.Round()
|
round := commit.Round()
|
||||||
|
|
||||||
for idx, precommit := range commit.Precommits {
|
for idx, precommit := range commit.Precommits {
|
||||||
if precommit == nil {
|
if precommit == nil || precommit.Vote == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if precommit.Height != height {
|
if precommit.Vote.Height != height {
|
||||||
return cmn.NewError("Blocks don't match - %d vs %d", round, precommit.Round)
|
return cmn.NewError("Blocks don't match - %d vs %d", round, precommit.Vote.Round)
|
||||||
}
|
}
|
||||||
if precommit.Round != round {
|
if precommit.Vote.Round != round {
|
||||||
return cmn.NewError("Invalid commit -- wrong round: %v vs %v", round, precommit.Round)
|
return cmn.NewError("Invalid commit -- wrong round: %v vs %v", round, precommit.Vote.Round)
|
||||||
}
|
}
|
||||||
if precommit.Type != VoteTypePrecommit {
|
if precommit.Vote.Type != VoteTypePrecommit {
|
||||||
return cmn.NewError("Invalid commit -- not precommit @ index %v", idx)
|
return cmn.NewError("Invalid commit -- not precommit @ index %v", idx)
|
||||||
}
|
}
|
||||||
// See if this validator is in oldVals.
|
// See if this validator is in oldVals.
|
||||||
idx, val := oldVals.GetByAddress(precommit.ValidatorAddress)
|
idx, val := oldVals.GetByAddress(precommit.Vote.ValidatorAddress)
|
||||||
if val == nil || seen[idx] {
|
if val == nil || seen[idx] {
|
||||||
continue // missing or double vote...
|
continue // missing or double vote...
|
||||||
}
|
}
|
||||||
seen[idx] = true
|
seen[idx] = true
|
||||||
|
|
||||||
// Validate signature.
|
// Validate signature.
|
||||||
precommitSignBytes := precommit.SignBytes(chainID)
|
precommitSignBytes := precommit.Vote.SignBytes()
|
||||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||||
return cmn.NewError("Invalid commit -- invalid signature: %v", precommit)
|
return cmn.NewError("Invalid commit -- invalid signature: %v", precommit)
|
||||||
}
|
}
|
||||||
// Good precommit!
|
// Good precommit!
|
||||||
if blockID.Equals(precommit.BlockID) {
|
if blockID.Equals(precommit.Vote.BlockID) {
|
||||||
oldVotingPower += val.VotingPower
|
oldVotingPower += val.VotingPower
|
||||||
} else {
|
} else {
|
||||||
// It's OK that the BlockID doesn't match. We include stray
|
// It's OK that the BlockID doesn't match. We include stray
|
||||||
|
@ -379,7 +379,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
|||||||
chainID := "mychainID"
|
chainID := "mychainID"
|
||||||
blockID := BlockID{Hash: []byte("hello")}
|
blockID := BlockID{Hash: []byte("hello")}
|
||||||
height := int64(5)
|
height := int64(5)
|
||||||
vote := &Vote{
|
vote := &UnsignedVote{
|
||||||
ValidatorAddress: v1.Address,
|
ValidatorAddress: v1.Address,
|
||||||
ValidatorIndex: 0,
|
ValidatorIndex: 0,
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -387,13 +387,14 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
|||||||
Timestamp: tmtime.Now(),
|
Timestamp: tmtime.Now(),
|
||||||
Type: VoteTypePrecommit,
|
Type: VoteTypePrecommit,
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
|
ChainID: chainID,
|
||||||
}
|
}
|
||||||
sig, err := privKey.Sign(vote.SignBytes(chainID))
|
sig, err := privKey.Sign(vote.SignBytes())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
vote.Signature = sig
|
|
||||||
commit := &Commit{
|
commit := &Commit{
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
Precommits: []*Vote{vote},
|
Precommits: []*SignedVote{&SignedVote{Vote: vote, Signature: sig}},
|
||||||
}
|
}
|
||||||
|
|
||||||
badChainID := "notmychainID"
|
badChainID := "notmychainID"
|
||||||
@ -401,7 +402,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
|||||||
badHeight := height + 1
|
badHeight := height + 1
|
||||||
badCommit := &Commit{
|
badCommit := &Commit{
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
Precommits: []*Vote{nil},
|
Precommits: []*SignedVote{nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
// test some error cases
|
// test some error cases
|
||||||
@ -420,7 +421,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
|||||||
|
|
||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit)
|
err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit)
|
||||||
assert.NotNil(t, err, i)
|
assert.NotNil(t, err, "test-case: %d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test a good one
|
// test a good one
|
||||||
|
@ -33,7 +33,7 @@ func (err *ErrVoteConflictingVotes) Error() string {
|
|||||||
return fmt.Sprintf("Conflicting votes from validator %v", err.PubKey.Address())
|
return fmt.Sprintf("Conflicting votes from validator %v", err.PubKey.Address())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConflictingVoteError(val *Validator, voteA, voteB *Vote) *ErrVoteConflictingVotes {
|
func NewConflictingVoteError(val *Validator, voteA, voteB *SignedVote) *ErrVoteConflictingVotes {
|
||||||
return &ErrVoteConflictingVotes{
|
return &ErrVoteConflictingVotes{
|
||||||
&DuplicateVoteEvidence{
|
&DuplicateVoteEvidence{
|
||||||
PubKey: val.PubKey,
|
PubKey: val.PubKey,
|
||||||
@ -65,7 +65,7 @@ func IsVoteTypeValid(type_ byte) bool {
|
|||||||
type Address = cmn.HexBytes
|
type Address = cmn.HexBytes
|
||||||
|
|
||||||
// Represents a prevote, precommit, or commit vote from validators for consensus.
|
// Represents a prevote, precommit, or commit vote from validators for consensus.
|
||||||
type Vote struct {
|
type UnsignedVote struct {
|
||||||
ValidatorAddress Address `json:"validator_address"`
|
ValidatorAddress Address `json:"validator_address"`
|
||||||
ValidatorIndex int `json:"validator_index"`
|
ValidatorIndex int `json:"validator_index"`
|
||||||
Height int64 `json:"height"`
|
Height int64 `json:"height"`
|
||||||
@ -76,14 +76,9 @@ type Vote struct {
|
|||||||
ChainID string `json:"chain_id"`
|
ChainID string `json:"chain_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignVoteRequest struct {
|
type SignedVote struct {
|
||||||
Vote Vote
|
Vote *UnsignedVote
|
||||||
}
|
|
||||||
|
|
||||||
type SignVoteReply struct {
|
|
||||||
Vote Vote
|
|
||||||
Signature []byte
|
Signature []byte
|
||||||
Err Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
@ -91,7 +86,7 @@ type Error struct {
|
|||||||
Description string
|
Description string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vote *Vote) SignBytes() []byte {
|
func (vote *UnsignedVote) SignBytes() []byte {
|
||||||
bz, err := cdc.MarshalBinary(vote)
|
bz, err := cdc.MarshalBinary(vote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -99,14 +94,14 @@ func (vote *Vote) SignBytes() []byte {
|
|||||||
return bz
|
return bz
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vote *Vote) Copy() *Vote {
|
func (vote *UnsignedVote) Copy() *UnsignedVote {
|
||||||
voteCopy := *vote
|
voteCopy := *vote
|
||||||
return &voteCopy
|
return &voteCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vote *Vote) String() string {
|
func (vote *UnsignedVote) String() string {
|
||||||
if vote == nil {
|
if vote == nil {
|
||||||
return "nil-Vote"
|
return "nil-UnsignedVote"
|
||||||
}
|
}
|
||||||
var typeString string
|
var typeString string
|
||||||
switch vote.Type {
|
switch vote.Type {
|
||||||
@ -118,20 +113,24 @@ func (vote *Vote) String() string {
|
|||||||
cmn.PanicSanity("Unknown vote type")
|
cmn.PanicSanity("Unknown vote type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}",
|
return fmt.Sprintf("UnsignedVote{%v:%X %v/%02d/%v(%v) %X @ %s}",
|
||||||
vote.ValidatorIndex, cmn.Fingerprint(vote.ValidatorAddress),
|
vote.ValidatorIndex, cmn.Fingerprint(vote.ValidatorAddress),
|
||||||
vote.Height, vote.Round, vote.Type, typeString,
|
vote.Height, vote.Round, vote.Type, typeString,
|
||||||
cmn.Fingerprint(vote.BlockID.Hash),
|
cmn.Fingerprint(vote.BlockID.Hash),
|
||||||
cmn.Fingerprint(vote.Signature),
|
// TODO(ismail): add corresponding
|
||||||
|
//cmn.Fingerprint(vote.Signature),
|
||||||
CanonicalTime(vote.Timestamp))
|
CanonicalTime(vote.Timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
|
func (vote *SignedVote) Verify(pubKey crypto.PubKey) error {
|
||||||
if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) {
|
if vote == nil || vote.Vote == nil {
|
||||||
|
return errors.New("called verify on nil/empty SignedVote")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pubKey.Address(), vote.Vote.ValidatorAddress) {
|
||||||
return ErrVoteInvalidValidatorAddress
|
return ErrVoteInvalidValidatorAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) {
|
if !pubKey.VerifyBytes(vote.Vote.SignBytes(), vote.Signature) {
|
||||||
return ErrVoteInvalidSignature
|
return ErrVoteInvalidSignature
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -60,7 +60,7 @@ type VoteSet struct {
|
|||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
votesBitArray *cmn.BitArray
|
votesBitArray *cmn.BitArray
|
||||||
votes []*Vote // Primary votes to share
|
votes []*SignedVote // 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 *BlockID // 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
|
||||||
@ -79,7 +79,7 @@ func NewVoteSet(chainID string, height int64, round int, type_ byte, valSet *Val
|
|||||||
type_: type_,
|
type_: type_,
|
||||||
valSet: valSet,
|
valSet: valSet,
|
||||||
votesBitArray: cmn.NewBitArray(valSet.Size()),
|
votesBitArray: cmn.NewBitArray(valSet.Size()),
|
||||||
votes: make([]*Vote, valSet.Size()),
|
votes: make([]*SignedVote, valSet.Size()),
|
||||||
sum: 0,
|
sum: 0,
|
||||||
maj23: nil,
|
maj23: nil,
|
||||||
votesByBlock: make(map[string]*blockVotes, valSet.Size()),
|
votesByBlock: make(map[string]*blockVotes, valSet.Size()),
|
||||||
@ -127,8 +127,8 @@ func (voteSet *VoteSet) Size() int {
|
|||||||
// Conflicting votes return added=*, err=ErrVoteConflictingVotes.
|
// Conflicting votes return added=*, err=ErrVoteConflictingVotes.
|
||||||
// NOTE: vote should not be mutated after adding.
|
// NOTE: vote should not be mutated after adding.
|
||||||
// NOTE: VoteSet must not be nil
|
// NOTE: VoteSet must not be nil
|
||||||
// NOTE: Vote must not be nil
|
// NOTE: UnsignedVote must not be nil
|
||||||
func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
|
func (voteSet *VoteSet) AddVote(vote *SignedVote) (added bool, err error) {
|
||||||
if voteSet == nil {
|
if voteSet == nil {
|
||||||
cmn.PanicSanity("AddVote() on nil VoteSet")
|
cmn.PanicSanity("AddVote() on nil VoteSet")
|
||||||
}
|
}
|
||||||
@ -139,13 +139,13 @@ func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Validates as much as possible before attempting to verify the signature.
|
// NOTE: Validates as much as possible before attempting to verify the signature.
|
||||||
func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
func (voteSet *VoteSet) addVote(vote *SignedVote) (added bool, err error) {
|
||||||
if vote == nil {
|
if vote == nil || vote.Vote == nil {
|
||||||
return false, ErrVoteNil
|
return false, ErrVoteNil
|
||||||
}
|
}
|
||||||
valIndex := vote.ValidatorIndex
|
valIndex := vote.Vote.ValidatorIndex
|
||||||
valAddr := vote.ValidatorAddress
|
valAddr := vote.Vote.ValidatorAddress
|
||||||
blockKey := vote.BlockID.Key()
|
blockKey := vote.Vote.BlockID.Key()
|
||||||
|
|
||||||
// Ensure that validator index was set
|
// Ensure that validator index was set
|
||||||
if valIndex < 0 {
|
if valIndex < 0 {
|
||||||
@ -155,12 +155,12 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the step matches.
|
// Make sure the step matches.
|
||||||
if (vote.Height != voteSet.height) ||
|
if (vote.Vote.Height != voteSet.height) ||
|
||||||
(vote.Round != voteSet.round) ||
|
(vote.Vote.Round != voteSet.round) ||
|
||||||
(vote.Type != voteSet.type_) {
|
(vote.Vote.Type != voteSet.type_) {
|
||||||
return false, errors.Wrapf(ErrVoteUnexpectedStep, "Got %d/%d/%d, expected %d/%d/%d",
|
return false, errors.Wrapf(ErrVoteUnexpectedStep, "Got %d/%d/%d, expected %d/%d/%d",
|
||||||
voteSet.height, voteSet.round, voteSet.type_,
|
voteSet.height, voteSet.round, voteSet.type_,
|
||||||
vote.Height, vote.Round, vote.Type)
|
vote.Vote.Height, vote.Vote.Round, vote.Vote.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that signer is a validator.
|
// Ensure that signer is a validator.
|
||||||
@ -186,7 +186,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check signature.
|
// Check signature.
|
||||||
if err := vote.Verify(voteSet.chainID, val.PubKey); err != nil {
|
if err := vote.Verify(val.PubKey); err != nil {
|
||||||
return false, errors.Wrapf(err, "Failed to verify vote with ChainID %s and PubKey %s", voteSet.chainID, val.PubKey)
|
return false, errors.Wrapf(err, "Failed to verify vote with ChainID %s and PubKey %s", voteSet.chainID, val.PubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +202,8 @@ 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 *SignedVote, ok bool) {
|
||||||
if existing := voteSet.votes[valIndex]; existing != nil && existing.BlockID.Key() == blockKey {
|
if existing := voteSet.votes[valIndex]; existing != nil && existing.Vote != nil && existing.Vote.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 {
|
||||||
@ -214,12 +214,12 @@ func (voteSet *VoteSet) getVote(valIndex int, blockKey string) (vote *Vote, ok b
|
|||||||
|
|
||||||
// Assumes signature is valid.
|
// Assumes signature is valid.
|
||||||
// If conflicting vote exists, returns it.
|
// If conflicting vote exists, returns it.
|
||||||
func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower int64) (added bool, conflicting *Vote) {
|
func (voteSet *VoteSet) addVerifiedVote(vote *SignedVote, blockKey string, votingPower int64) (added bool, conflicting *SignedVote) {
|
||||||
valIndex := vote.ValidatorIndex
|
valIndex := vote.Vote.ValidatorIndex
|
||||||
|
|
||||||
// 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.BlockID.Equals(vote.BlockID) {
|
if existing.Vote.BlockID.Equals(vote.Vote.BlockID) {
|
||||||
cmn.PanicSanity("addVerifiedVote does not expect duplicate votes")
|
cmn.PanicSanity("addVerifiedVote does not expect duplicate votes")
|
||||||
} else {
|
} else {
|
||||||
conflicting = existing
|
conflicting = existing
|
||||||
@ -269,7 +269,7 @@ 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 {
|
||||||
maj23BlockID := vote.BlockID
|
maj23BlockID := vote.Vote.BlockID
|
||||||
voteSet.maj23 = &maj23BlockID
|
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 {
|
||||||
@ -346,7 +346,7 @@ func (voteSet *VoteSet) BitArrayByBlockID(blockID BlockID) *cmn.BitArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: if validator has conflicting votes, returns "canonical" vote
|
// NOTE: if validator has conflicting votes, returns "canonical" vote
|
||||||
func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
|
func (voteSet *VoteSet) GetByIndex(valIndex int) *SignedVote {
|
||||||
if voteSet == nil {
|
if voteSet == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
|
|||||||
return voteSet.votes[valIndex]
|
return voteSet.votes[valIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
|
func (voteSet *VoteSet) GetByAddress(address []byte) *SignedVote {
|
||||||
if voteSet == nil {
|
if voteSet == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -433,10 +433,10 @@ func (voteSet *VoteSet) StringIndented(indent string) string {
|
|||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
voteStrings := make([]string, len(voteSet.votes))
|
voteStrings := make([]string, len(voteSet.votes))
|
||||||
for i, vote := range voteSet.votes {
|
for i, vote := range voteSet.votes {
|
||||||
if vote == nil {
|
if vote == nil || vote.Vote == nil {
|
||||||
voteStrings[i] = "nil-Vote"
|
voteStrings[i] = "nil-UnsignedVote"
|
||||||
} else {
|
} else {
|
||||||
voteStrings[i] = vote.String()
|
voteStrings[i] = vote.Vote.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`VoteSet{
|
return fmt.Sprintf(`VoteSet{
|
||||||
@ -498,10 +498,10 @@ func (voteSet *VoteSet) VoteStrings() []string {
|
|||||||
func (voteSet *VoteSet) voteStrings() []string {
|
func (voteSet *VoteSet) voteStrings() []string {
|
||||||
voteStrings := make([]string, len(voteSet.votes))
|
voteStrings := make([]string, len(voteSet.votes))
|
||||||
for i, vote := range voteSet.votes {
|
for i, vote := range voteSet.votes {
|
||||||
if vote == nil {
|
if vote == nil || vote.Vote == nil {
|
||||||
voteStrings[i] = "nil-Vote"
|
voteStrings[i] = "nil-Vote"
|
||||||
} else {
|
} else {
|
||||||
voteStrings[i] = vote.String()
|
voteStrings[i] = vote.Vote.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return voteStrings
|
return voteStrings
|
||||||
@ -541,7 +541,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For every validator, get the precommit
|
// For every validator, get the precommit
|
||||||
votesCopy := make([]*Vote, len(voteSet.votes))
|
votesCopy := make([]*SignedVote, len(voteSet.votes))
|
||||||
copy(votesCopy, voteSet.votes)
|
copy(votesCopy, voteSet.votes)
|
||||||
return &Commit{
|
return &Commit{
|
||||||
BlockID: *voteSet.maj23,
|
BlockID: *voteSet.maj23,
|
||||||
@ -560,7 +560,7 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
|||||||
type blockVotes struct {
|
type blockVotes struct {
|
||||||
peerMaj23 bool // peer claims to have maj23
|
peerMaj23 bool // peer claims to have maj23
|
||||||
bitArray *cmn.BitArray // valIndex -> hasVote?
|
bitArray *cmn.BitArray // valIndex -> hasVote?
|
||||||
votes []*Vote // valIndex -> *Vote
|
votes []*SignedVote // valIndex -> *UnsignedVote
|
||||||
sum int64 // vote sum
|
sum int64 // vote sum
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,13 +568,13 @@ func newBlockVotes(peerMaj23 bool, numValidators int) *blockVotes {
|
|||||||
return &blockVotes{
|
return &blockVotes{
|
||||||
peerMaj23: peerMaj23,
|
peerMaj23: peerMaj23,
|
||||||
bitArray: cmn.NewBitArray(numValidators),
|
bitArray: cmn.NewBitArray(numValidators),
|
||||||
votes: make([]*Vote, numValidators),
|
votes: make([]*SignedVote, numValidators),
|
||||||
sum: 0,
|
sum: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vs *blockVotes) addVerifiedVote(vote *Vote, votingPower int64) {
|
func (vs *blockVotes) addVerifiedVote(vote *SignedVote, votingPower int64) {
|
||||||
valIndex := vote.ValidatorIndex
|
valIndex := vote.Vote.ValidatorIndex
|
||||||
if existing := vs.votes[valIndex]; existing == nil {
|
if existing := vs.votes[valIndex]; existing == nil {
|
||||||
vs.bitArray.SetIndex(valIndex, true)
|
vs.bitArray.SetIndex(valIndex, true)
|
||||||
vs.votes[valIndex] = vote
|
vs.votes[valIndex] = vote
|
||||||
@ -582,7 +582,7 @@ func (vs *blockVotes) addVerifiedVote(vote *Vote, votingPower int64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vs *blockVotes) getByIndex(index int) *Vote {
|
func (vs *blockVotes) getByIndex(index int) *SignedVote {
|
||||||
if vs == nil {
|
if vs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -598,6 +598,6 @@ type VoteSetReader interface {
|
|||||||
Type() byte
|
Type() byte
|
||||||
Size() int
|
Size() int
|
||||||
BitArray() *cmn.BitArray
|
BitArray() *cmn.BitArray
|
||||||
GetByIndex(int) *Vote
|
GetByIndex(int) *UnsignedVote
|
||||||
IsCommit() bool
|
IsCommit() bool
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ func randVoteSet(height int64, round int, type_ byte, numValidators int, votingP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different validator address/index
|
// Convenience: Return new vote with different validator address/index
|
||||||
func withValidator(vote *Vote, addr []byte, idx int) *Vote {
|
func withValidator(vote *UnsignedVote, addr []byte, idx int) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.ValidatorAddress = addr
|
vote.ValidatorAddress = addr
|
||||||
vote.ValidatorIndex = idx
|
vote.ValidatorIndex = idx
|
||||||
@ -25,35 +25,35 @@ func withValidator(vote *Vote, addr []byte, idx int) *Vote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different height
|
// Convenience: Return new vote with different height
|
||||||
func withHeight(vote *Vote, height int64) *Vote {
|
func withHeight(vote *UnsignedVote, height int64) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Height = height
|
vote.Height = height
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different round
|
// Convenience: Return new vote with different round
|
||||||
func withRound(vote *Vote, round int) *Vote {
|
func withRound(vote *UnsignedVote, round int) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Round = round
|
vote.Round = round
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different type
|
// Convenience: Return new vote with different type
|
||||||
func withType(vote *Vote, type_ byte) *Vote {
|
func withType(vote *UnsignedVote, type_ byte) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Type = type_
|
vote.Type = type_
|
||||||
return vote
|
return 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 *UnsignedVote, blockHash []byte) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockID.Hash = 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 *UnsignedVote, blockPartsHeader PartSetHeader) *UnsignedVote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockID.PartsHeader = blockPartsHeader
|
vote.BlockID.PartsHeader = blockPartsHeader
|
||||||
return vote
|
return vote
|
||||||
@ -77,7 +77,7 @@ func TestAddVote(t *testing.T) {
|
|||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
|
|
||||||
vote := &Vote{
|
vote := &UnsignedVote{
|
||||||
ValidatorAddress: val0.GetAddress(),
|
ValidatorAddress: val0.GetAddress(),
|
||||||
ValidatorIndex: 0, // since privValidators are in order
|
ValidatorIndex: 0, // since privValidators are in order
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -107,7 +107,7 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
height, round := int64(1), 0
|
height, round := int64(1), 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
voteProto := &Vote{
|
voteProto := &UnsignedVote{
|
||||||
ValidatorAddress: nil, // NOTE: must fill in
|
ValidatorAddress: nil, // NOTE: must fill in
|
||||||
ValidatorIndex: -1, // NOTE: must fill in
|
ValidatorIndex: -1, // NOTE: must fill in
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -164,7 +164,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
blockPartsTotal := 123
|
blockPartsTotal := 123
|
||||||
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
|
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
|
||||||
|
|
||||||
voteProto := &Vote{
|
voteProto := &UnsignedVote{
|
||||||
ValidatorAddress: nil, // NOTE: must fill in
|
ValidatorAddress: nil, // NOTE: must fill in
|
||||||
ValidatorIndex: -1, // NOTE: must fill in
|
ValidatorIndex: -1, // NOTE: must fill in
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -259,7 +259,7 @@ func TestBadVotes(t *testing.T) {
|
|||||||
height, round := int64(1), 0
|
height, round := int64(1), 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
voteProto := &Vote{
|
voteProto := &UnsignedVote{
|
||||||
ValidatorAddress: nil,
|
ValidatorAddress: nil,
|
||||||
ValidatorIndex: -1,
|
ValidatorIndex: -1,
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -321,7 +321,7 @@ func TestConflicts(t *testing.T) {
|
|||||||
blockHash1 := cmn.RandBytes(32)
|
blockHash1 := cmn.RandBytes(32)
|
||||||
blockHash2 := cmn.RandBytes(32)
|
blockHash2 := cmn.RandBytes(32)
|
||||||
|
|
||||||
voteProto := &Vote{
|
voteProto := &UnsignedVote{
|
||||||
ValidatorAddress: nil,
|
ValidatorAddress: nil,
|
||||||
ValidatorIndex: -1,
|
ValidatorIndex: -1,
|
||||||
Height: height,
|
Height: height,
|
||||||
@ -450,7 +450,7 @@ func TestMakeCommit(t *testing.T) {
|
|||||||
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrecommit, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrecommit, 10, 1)
|
||||||
blockHash, blockPartsHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)}
|
blockHash, blockPartsHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)}
|
||||||
|
|
||||||
voteProto := &Vote{
|
voteProto := &UnsignedVote{
|
||||||
ValidatorAddress: nil,
|
ValidatorAddress: nil,
|
||||||
ValidatorIndex: -1,
|
ValidatorIndex: -1,
|
||||||
Height: height,
|
Height: height,
|
||||||
|
@ -12,21 +12,21 @@ import (
|
|||||||
tmtime "github.com/tendermint/tendermint/types/time"
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func examplePrevote() *Vote {
|
func examplePrevote() *UnsignedVote {
|
||||||
return exampleVote(VoteTypePrevote)
|
return exampleVote(VoteTypePrevote)
|
||||||
}
|
}
|
||||||
|
|
||||||
func examplePrecommit() *Vote {
|
func examplePrecommit() *UnsignedVote {
|
||||||
return exampleVote(VoteTypePrecommit)
|
return exampleVote(VoteTypePrecommit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exampleVote(t byte) *Vote {
|
func exampleVote(t byte) *UnsignedVote {
|
||||||
var stamp, err = time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z")
|
var stamp, err = time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Vote{
|
return &UnsignedVote{
|
||||||
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
||||||
ValidatorIndex: 56789,
|
ValidatorIndex: 56789,
|
||||||
Height: 12345,
|
Height: 12345,
|
||||||
@ -40,18 +40,20 @@ func exampleVote(t byte) *Vote {
|
|||||||
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
|
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ChainID: "test_chain_id",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVoteSignable(t *testing.T) {
|
func TestVoteSignable(t *testing.T) {
|
||||||
|
t.Skip("TODO(ismail): switch to amino")
|
||||||
vote := examplePrecommit()
|
vote := examplePrecommit()
|
||||||
signBytes := vote.SignBytes("test_chain_id")
|
signBytes := vote.SignBytes()
|
||||||
signStr := string(signBytes)
|
signStr := string(signBytes)
|
||||||
|
|
||||||
expected := `{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"8B01023386C371778ECB6368573E539AFC3CC860","parts":{"hash":"72DB3D959635DFF1BB567BEDAA70573392C51596","total":"1000000"}},"height":"12345","round":"2","timestamp":"2017-12-25T03:00:01.234Z","type":2}`
|
expected := `{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"8B01023386C371778ECB6368573E539AFC3CC860","parts":{"hash":"72DB3D959635DFF1BB567BEDAA70573392C51596","total":"1000000"}},"height":"12345","round":"2","timestamp":"2017-12-25T03:00:01.234Z","type":2}`
|
||||||
if signStr != expected {
|
if signStr != expected {
|
||||||
// NOTE: when this fails, you probably want to fix up consensus/replay_test too
|
// NOTE: when this fails, you probably want to fix up consensus/replay_test too
|
||||||
t.Errorf("Got unexpected sign string for Vote. Expected:\n%v\nGot:\n%v", expected, signStr)
|
t.Errorf("Got unexpected sign string for UnsignedVote. Expected:\n%v\nGot:\n%v", expected, signStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,25 +62,25 @@ func TestVoteVerifySignature(t *testing.T) {
|
|||||||
pubkey := privVal.GetPubKey()
|
pubkey := privVal.GetPubKey()
|
||||||
|
|
||||||
vote := examplePrecommit()
|
vote := examplePrecommit()
|
||||||
signBytes := vote.SignBytes("test_chain_id")
|
signBytes := vote.SignBytes()
|
||||||
|
|
||||||
// sign it
|
// sign it
|
||||||
err := privVal.SignVote("test_chain_id", vote)
|
signedVote, err := privVal.SignVote(vote)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// verify the same vote
|
// verify the same vote
|
||||||
valid := pubkey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature)
|
valid := pubkey.VerifyBytes(vote.SignBytes(), signedVote.Signature)
|
||||||
require.True(t, valid)
|
require.True(t, valid)
|
||||||
|
|
||||||
// serialize, deserialize and verify again....
|
// serialize, deserialize and verify again....
|
||||||
precommit := new(Vote)
|
precommit := new(SignedVote)
|
||||||
bs, err := cdc.MarshalBinary(vote)
|
bs, err := cdc.MarshalBinary(signedVote)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = cdc.UnmarshalBinary(bs, &precommit)
|
err = cdc.UnmarshalBinary(bs, &precommit)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// verify the transmitted vote
|
// verify the transmitted vote
|
||||||
newSignBytes := precommit.SignBytes("test_chain_id")
|
newSignBytes := precommit.Vote.SignBytes()
|
||||||
require.Equal(t, string(signBytes), string(newSignBytes))
|
require.Equal(t, string(signBytes), string(newSignBytes))
|
||||||
valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
|
valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
|
||||||
require.True(t, valid)
|
require.True(t, valid)
|
||||||
@ -99,7 +101,7 @@ func TestIsVoteTypeValid(t *testing.T) {
|
|||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(st *testing.T) {
|
t.Run(tt.name, func(st *testing.T) {
|
||||||
if rs := IsVoteTypeValid(tt.in); rs != tt.out {
|
if rs := IsVoteTypeValid(tt.in); rs != tt.out {
|
||||||
t.Errorf("Got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out)
|
t.Errorf("Got unexpected UnsignedVote type. Expected:\n%v\nGot:\n%v", rs, tt.out)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -111,20 +113,21 @@ func TestVoteVerify(t *testing.T) {
|
|||||||
|
|
||||||
vote := examplePrevote()
|
vote := examplePrevote()
|
||||||
vote.ValidatorAddress = pubkey.Address()
|
vote.ValidatorAddress = pubkey.Address()
|
||||||
|
sv := &SignedVote{Vote: vote}
|
||||||
|
|
||||||
err := vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey())
|
err := sv.Verify(ed25519.GenPrivKey().PubKey())
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Equal(t, ErrVoteInvalidValidatorAddress, err)
|
assert.Equal(t, ErrVoteInvalidValidatorAddress, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = vote.Verify("test_chain_id", pubkey)
|
err = sv.Verify(pubkey)
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Equal(t, ErrVoteInvalidSignature, err)
|
assert.Equal(t, ErrVoteInvalidSignature, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxVoteBytes(t *testing.T) {
|
func TestMaxVoteBytes(t *testing.T) {
|
||||||
vote := &Vote{
|
vote := &UnsignedVote{
|
||||||
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
||||||
ValidatorIndex: math.MaxInt64,
|
ValidatorIndex: math.MaxInt64,
|
||||||
Height: math.MaxInt64,
|
Height: math.MaxInt64,
|
||||||
@ -141,11 +144,12 @@ func TestMaxVoteBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
privVal := NewMockPV()
|
privVal := NewMockPV()
|
||||||
err := privVal.SignVote("test_chain_id", vote)
|
sv, err := privVal.SignVote(vote)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
bz, err := cdc.MarshalBinary(vote)
|
bz, err := cdc.MarshalBinary(sv)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
// TODO(ismail): if we include the chainId in the vote this varies ...
|
||||||
|
// we need a max size for chainId too
|
||||||
assert.Equal(t, MaxVoteBytes, len(bz))
|
assert.Equal(t, MaxVoteBytes, len(bz))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user