8000 refactor(consensus): print err from SignAndCheckVote by melekes · Pull Request #2346 · cometbft/cometbft · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor(consensus): print err from SignAndCheckVote #2346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2443,7 +2443,7 @@ func (cs *State) signVote(

recoverable, err := types.SignAndCheckVote(vote, cs.privValidator, cs.state.ChainID, extEnabled && (msgType == types.PrecommitType))
if err != nil && !recoverable {
panic(fmt.Sprintf("non-recoverable error when signing vote (%d/%d)", vote.Height, vote.Round))
panic(fmt.Sprintf("non-recoverable error when signing vote %v: %v", vote, err))
}

return vote, err
Expand Down
27 changes: 18 additions & 9 deletions types/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ func NewConflictingVoteError(vote1, vote2 *Vote) *ErrVoteConflictingVotes {
}
}

// The vote extension is only valid for non-nil precommits.
type ErrVoteExtensionInvalid struct {
ExtSignature []byte
}

func (err *ErrVoteExtensionInvalid) Error() string {
return fmt.Sprintf("extensions must be present IFF vote is a non-nil Precommit; extension signature: %X", err.ExtSignature)
}

// Address is hex bytes.
type Address = crypto.Address

Expand Down Expand Up @@ -401,6 +410,9 @@ func VotesToProto(votes []*Vote) []*cmtproto.Vote {
return res
}

// SignAndCheckVote signs the vote with the given privVal and checks the vote.
// It returns an error if the vote is invalid and a boolean indicating if the
// error is recoverable or not.
func SignAndCheckVote(
vote *Vote,
privVal PrivValidator,
Expand All @@ -409,33 +421,30 @@ func SignAndCheckVote(
) (bool, error) {
v := vote.ToProto()
if err := privVal.SignVote(chainID, v); err != nil {
// Failing to sign a vote has always been a recoverable error, this function keeps it that way
return true, err // true = recoverable
// Failing to sign a vote has always been a recoverable error, this
// function keeps it that way.
return true, err
}
vote.Signature = v.Signature

isPrecommit := vote.Type == PrecommitType
if !isPrecommit && extensionsEnabled {
// Non-recoverable because the caller passed parameters that don't make sense
return false, fmt.Errorf("only Precommit votes may have extensions enabled; vote type: %d", vote.Type)
return false, &ErrVoteExtensionInvalid{ExtSignature: v.ExtensionSignature}
}

isNil := vote.BlockID.IsNil()
extSignature := (len(v.ExtensionSignature) > 0)
if extSignature == (!isPrecommit || isNil) {
// Non-recoverable because the vote is malformed
return false, fmt.Errorf(
"extensions must be present IFF vote is a non-nil Precommit; present %t, vote type %d, is nil %t",
extSignature,
vote.Type,
isNil,
)
return false, &ErrVoteExtensionInvalid{ExtSignature: v.ExtensionSignature}
}

vote.ExtensionSignature = nil
if extensionsEnabled {
vote.ExtensionSignature = v.ExtensionSignature
}

vote.Timestamp = v.Timestamp

return true, nil
Expand Down
111 changes: 110 additions & 1 deletion types/vote_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"fmt"
"testing"
"time"

Expand All @@ -22,6 +23,7 @@ func examplePrevote() *Vote {

func examplePrecommit() *Vote {
vote := exampleVote(byte(PrecommitType))
vote.Extension = []byte("extension")
vote.ExtensionSignature = []byte("signature")
return vote
}
Expand Down Expand Up @@ -312,7 +314,7 @@ func TestVoteVerify(t *testing.T) {

func TestVoteString(t *testing.T) {
str := examplePrecommit().String()
expected := `Vote{56789:6AF1F4111082 12345/02/SIGNED_MSG_TYPE_PRECOMMIT(Precommit) 8B01023386C3 000000000000 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
expected := `Vote{56789:6AF1F4111082 12345/02/SIGNED_MSG_TYPE_PRECOMMIT(Precommit) 8B01023386C3 000000000000 657874656E73 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
if str != expected {
t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str)
}
Expand Down Expand Up @@ -490,3 +492,110 @@ func TestVoteProtobuf(t *testing.T) {
}
}
}

func TestSignAndCheckVote(t *testing.T) {
privVal := NewMockPV()

testCases := []struct {
name string
extensionsEnabled bool
vote *Vote
expectError bool
}{
{
name: "precommit with extension signature",
extensionsEnabled: true,
vote: examplePrecommit(),
expectError: false,
},
{
name: "precommit with extension signature",
extensionsEnabled: false,
vote: examplePrecommit(),
expectError: false,
},
{
name: "precommit with extension signature for a nil block",
extensionsEnabled: true,
vote: func() *Vote {
v := examplePrecommit()
v.BlockID = BlockID{make([]byte, 0), PartSetHeader{0, make([]byte, 0)}}
return v
}(),
expectError: true,
},
{
name: "precommit with extension signature for a nil block",
extensionsEnabled: false,
vote: func() *Vote {
v := examplePrecommit()
v.BlockID = BlockID{make([]byte, 0), PartSetHeader{0, make([]byte, 0)}}
return v
}(),
expectError: true,
},
{
name: "precommit without extension",
extensionsEnabled: true,
vote: func() *Vote {
v := examplePrecommit()
v.Extension = make([]byte, 0)
return v
}(),
expectError: false,
},
{
name: "precommit without extension",
extensionsEnabled: false,
vote: func() *Vote {
v := examplePrecommit()
v.Extension = make([]byte, 0)
return v
}(),
expectError: false,
},
{
name: "prevote",
extensionsEnabled: true,
vote: examplePrevote(),
expectError: true,
},
{
name: "prevote",
extensionsEnabled: false,
vote: examplePrevote(),
expectError: false,
},
{
name: "prevote with extension",
extensionsEnabled: true,
vote: func() *Vote {
v := examplePrevote()
v.Extension = []byte("extension")
return v
}(),
expectError: true,
},
{
name: "prevote with extension",
extensionsEnabled: false,
vote: func() *Vote {
v := examplePrevote()
v.Extension = []byte("extension")
return v
}(),
expectError: true,
},
}

for _, tc := range testCases {
t.Run(fmt.Sprintf("%s (extensionsEnabled: %t) ", tc.name, tc.extensionsEnabled), func(t *testing.T) {
_, err := SignAndCheckVote(tc.vote, privVal, "test_chain_id", tc.extensionsEnabled)
if tc.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
0