Skip to content

Commit

Permalink
Merge pull request #7 from greg-szabo/develop
Browse files Browse the repository at this point in the history
VE extension patch
  • Loading branch information
marcello33 authored Nov 27, 2024
2 parents c53688a + 4f9ee31 commit 809f7ba
Show file tree
Hide file tree
Showing 29 changed files with 1,053 additions and 429 deletions.
620 changes: 419 additions & 201 deletions abci/types/types.pb.go

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (vs *validatorStub) signVote(
hash []byte,
header types.PartSetHeader,
voteExtension []byte,
nonRpVoteExtension []byte,
extEnabled bool,
) (*types.Vote, error) {
pubKey, err := vs.PrivValidator.GetPubKey()
Expand All @@ -107,6 +108,7 @@ func (vs *validatorStub) signVote(
ValidatorAddress: pubKey.Address(),
ValidatorIndex: vs.Index,
Extension: voteExtension,
NonRpExtension: nonRpVoteExtension,
}
v := vote.ToProto()
if err = vs.PrivValidator.SignVote(test.DefaultTestChainID, v); err != nil {
Expand All @@ -118,32 +120,36 @@ func (vs *validatorStub) signVote(
v.Signature = vs.lastVote.Signature
v.Timestamp = vs.lastVote.Timestamp
v.ExtensionSignature = vs.lastVote.ExtensionSignature
v.NonRpExtensionSignature = vs.lastVote.NonRpExtensionSignature
}

vote.Signature = v.Signature
vote.Timestamp = v.Timestamp
vote.ExtensionSignature = v.ExtensionSignature
vote.NonRpExtensionSignature = v.NonRpExtensionSignature

if !extEnabled {
vote.ExtensionSignature = nil
vote.NonRpExtensionSignature = nil
}

return vote, err
}

// Sign vote for type/hash/header
func signVote(vs *validatorStub, voteType cmtproto.SignedMsgType, hash []byte, header types.PartSetHeader, extEnabled bool) *types.Vote {
var ext []byte
var ext, nonRpExt []byte
// Only non-nil precommits are allowed to carry vote extensions.
if extEnabled {
if voteType != cmtproto.PrecommitType {
panic(fmt.Errorf("vote type is not precommit but extensions enabled"))
}
if len(hash) != 0 || !header.IsZero() {
ext = []byte("extension")
nonRpExt = []byte("non_replay_protected_extension")
}
}
v, err := vs.signVote(voteType, hash, header, ext, extEnabled)
v, err := vs.signVote(voteType, hash, header, ext, nonRpExt, extEnabled)

if err != nil {
panic(fmt.Errorf("failed to sign vote: %v", err))
Expand Down Expand Up @@ -987,5 +993,6 @@ func signDataIsEqual(v1 *types.Vote, v2 *cmtproto.Vote) bool {
v1.Round == v2.Round &&
bytes.Equal(v1.ValidatorAddress.Bytes(), v2.GetValidatorAddress()) &&
v1.ValidatorIndex == v2.GetValidatorIndex() &&
bytes.Equal(v1.Extension, v2.Extension)
bytes.Equal(v1.Extension, v2.Extension) &&
bytes.Equal(v1.NonRpExtension, v2.NonRpExtension)
}
2 changes: 2 additions & 0 deletions consensus/invalid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ func invalidDoPrevoteFunc(t *testing.T, cs *State, sw *p2p.Switch, pv types.Priv
}
precommit.Signature = p.Signature
precommit.ExtensionSignature = p.ExtensionSignature
precommit.NonRpExtension = p.NonRpExtension
precommit.NonRpExtensionSignature = p.NonRpExtensionSignature
cs.privValidator = nil // disable priv val so we don't do normal votes

peers := sw.Peers().List()
Expand Down
1 change: 1 addition & 0 deletions consensus/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ func TestConsMsgsVectors(t *testing.T) {
}
vpb := v.ToProto()
v.Extension = []byte("extension")
// TODO bernd: extend test to cover v.NonRpExtension
vextPb := v.ToProto()

testCases := []struct {
Expand Down
3 changes: 3 additions & 0 deletions consensus/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,13 @@ func TestSwitchToConsensusVoteExtensions(t *testing.T) {
var veHeight int64
if testCase.includeExtensions {
require.NotNil(t, signedVote.ExtensionSignature)
require.NotNil(t, signedVote.NonRpExtensionSignature)
veHeight = testCase.storedHeight
} else {
require.Nil(t, signedVote.Extension)
require.Nil(t, signedVote.ExtensionSignature)
require.Nil(t, signedVote.NonRpExtension)
require.Nil(t, signedVote.NonRpExtensionSignature)
}

added, err := voteSet.AddVote(signedVote)
Expand Down
4 changes: 3 additions & 1 deletion consensus/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ func (cs *State) readReplayMessage(msg *TimedWALMessage, newStepSub types.Subscr
case *VoteMessage:
v := msg.Vote
cs.Logger.Info("Replay: Vote", "height", v.Height, "round", v.Round, "type", v.Type,
"blockID", v.BlockID, "peer", peerID, "extensionLen", len(v.Extension), "extSigLen", len(v.ExtensionSignature))
"blockID", v.BlockID, "peer", peerID,
"extensionLen", len(v.Extension), "extSigLen", len(v.ExtensionSignature),
"nrp-extensionLen", len(v.NonRpExtension), "nrp-extSigLen", len(v.NonRpExtensionSignature))
}

cs.handleMsg(m)
Expand Down
8 changes: 6 additions & 2 deletions consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2123,6 +2123,8 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
"cs_height", cs.Height,
"extLen", len(vote.Extension),
"extSigLen", len(vote.ExtensionSignature),
"nrpExtLen", len(vote.NonRpExtension),
"nrpExtSigLen", len(vote.NonRpExtensionSignature),
)

if vote.Height < cs.Height || (vote.Height == cs.Height && vote.Round < cs.Round) {
Expand Down Expand Up @@ -2217,7 +2219,8 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
// TODO punish a peer if it sent a vote with an extension when the feature
// is disabled on the network.
// https://github.com/tendermint/tendermint/issues/8565
if len(vote.Extension) > 0 || len(vote.ExtensionSignature) > 0 {
if len(vote.Extension) > 0 || len(vote.ExtensionSignature) > 0 ||
len(vote.NonRpExtension) > 0 || len(vote.NonRpExtensionSignature) > 0 {
return false, fmt.Errorf("received vote with vote extension for height %v (extensions disabled) from peer ID %s", vote.Height, peerID)
}
}
Expand Down Expand Up @@ -2394,11 +2397,12 @@ func (cs *State) signVote(
// if the signedMessage type is for a non-nil precommit, add
// VoteExtension
if extEnabled {
ext, err := cs.blockExec.ExtendVote(context.TODO(), vote, block, cs.state)
ext, nonRpExt, err := cs.blockExec.ExtendVote(context.TODO(), vote, block, cs.state)
if err != nil {
return nil, err
}
vote.Extension = ext
vote.NonRpExtension = nonRpExt
}
}

Expand Down
39 changes: 26 additions & 13 deletions consensus/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1564,10 +1564,11 @@ func TestExtendVoteCalledWhenEnabled(t *testing.T) {
addr := pv.Address()
if testCase.enabled {
m.AssertCalled(t, "VerifyVoteExtension", context.TODO(), &abci.RequestVerifyVoteExtension{
Hash: blockID.Hash,
ValidatorAddress: addr,
Height: height,
VoteExtension: []byte("extension"),
Hash: blockID.Hash,
ValidatorAddress: addr,
Height: height,
VoteExtension: []byte("extension"),
NonRpVoteExtension: []byte("non_replay_protected_extension"),
})
} else {
m.AssertNotCalled(t, "VerifyVoteExtension", mock.Anything, mock.Anything)
Expand Down Expand Up @@ -1638,10 +1639,11 @@ func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) {
addr = pv.Address()

m.AssertNotCalled(t, "VerifyVoteExtension", context.TODO(), &abci.RequestVerifyVoteExtension{
Hash: blockID.Hash,
ValidatorAddress: addr,
Height: height,
VoteExtension: []byte("extension"),
Hash: blockID.Hash,
ValidatorAddress: addr,
Height: height,
VoteExtension: []byte("extension"),
NonRpVoteExtension: []byte("non_replay_protected_extension"),
})
}

Expand All @@ -1659,10 +1661,17 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
[]byte("extension 2"),
[]byte("extension 3"),
}
nonRpVoteExtensions := [][]byte{
[]byte("nrp-extension 0"),
[]byte("nrp-extension 1"),
[]byte("nrp-extension 2"),
[]byte("nrp-extension 3"),
}

m := abcimocks.NewApplication(t)
m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{
VoteExtension: voteExtensions[0],
VoteExtension: voteExtensions[0],
NonRpExtension: nonRpVoteExtensions[0],
}, nil)
m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil)

Expand Down Expand Up @@ -1700,7 +1709,8 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {

// create a precommit for each validator with the associated vote extension.
for i, vs := range vss[1:] {
signAddPrecommitWithExtension(t, cs1, blockID.Hash, blockID.PartSetHeader, voteExtensions[i+1], vs)
signAddPrecommitWithExtension(t, cs1, blockID.Hash, blockID.PartSetHeader,
voteExtensions[i+1], nonRpVoteExtensions[i+1], vs)
}

ensurePrevote(voteCh, height, round)
Expand Down Expand Up @@ -1728,6 +1738,7 @@ func TestPrepareProposalReceivesVoteExtensions(t *testing.T) {
for i := range vss {
vote := &rpp.LocalLastCommit.Votes[i]
require.Equal(t, vote.VoteExtension, voteExtensions[i])
require.Equal(t, vote.NonRpVoteExtension, nonRpVoteExtensions[i])

require.NotZero(t, len(vote.ExtensionSignature))
cve := cmtproto.CanonicalVoteExtension{
Expand Down Expand Up @@ -1915,13 +1926,14 @@ func TestVoteExtensionEnableHeight(t *testing.T) {
signAddVotes(cs1, cmtproto.PrevoteType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), false, vss[1:]...)
ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash())

var ext []byte
var ext, nonRpExt []byte
if testCase.hasExtension {
ext = []byte("extension")
nonRpExt = []byte("non_replay_protected_extension")
}

for _, vs := range vss[1:] {
vote, err := vs.signVote(cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), ext, testCase.hasExtension)
vote, err := vs.signVote(cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), ext, nonRpExt, testCase.hasExtension)
require.NoError(t, err)
addVotes(cs1, vote)
}
Expand Down Expand Up @@ -2582,9 +2594,10 @@ func signAddPrecommitWithExtension(
hash []byte,
header types.PartSetHeader,
extension []byte,
nonRpExtension []byte,
stub *validatorStub,
) {
v, err := stub.signVote(cmtproto.PrecommitType, hash, header, extension, true)
v, err := stub.signVote(cmtproto.PrecommitType, hash, header, extension, nonRpExtension, true)
require.NoError(t, err, "failed to sign vote")
addVotes(cs, v)
}
Expand Down
1 change: 1 addition & 0 deletions consensus/types/height_vote_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func TestInconsistentExtensionData(t *testing.T) {
hvsE := NewExtendedHeightVoteSet(test.DefaultTestChainID, 1, valSet)
voteNoExt := makeVoteHR(1, 0, 20, privVals)
voteNoExt.Extension, voteNoExt.ExtensionSignature = nil, nil
voteNoExt.NonRpExtension, voteNoExt.NonRpExtensionSignature = nil, nil
require.Panics(t, func() {
_, _ = hvsE.AddVote(voteNoExt, "peer1", false)
})
Expand Down
3 changes: 2 additions & 1 deletion evidence/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,8 @@ func makeExtCommit(height int64, valAddr []byte) *types.ExtendedCommit {
Timestamp: defaultEvidenceTime,
Signature: []byte("Signature"),
},
ExtensionSignature: []byte("Extended Signature"),
ExtensionSignature: []byte("Extended Signature"),
NonRpExtensionSignature: []byte("Non Replay Protected Extended Signature"),
}},
}
}
Expand Down
8 changes: 6 additions & 2 deletions light/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,17 @@ func makeVote(header *types.Header, valset *types.ValidatorSet,
}
vote.Signature = sig

extSignBytes := types.VoteExtensionSignBytes(header.ChainID, v)
extSignBytes, nonRpExtSignBytes := types.VoteExtensionSignBytes(header.ChainID, v)
extSig, err := key.Sign(extSignBytes)
if err != nil {
panic(err)
}
nonRpExtSig, err := key.Sign(nonRpExtSignBytes)
if err != nil {
panic(err)
}
vote.ExtensionSignature = extSig

vote.NonRpExtensionSignature = nonRpExtSig
return vote
}

Expand Down
11 changes: 9 additions & 2 deletions privval/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,18 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error {
// precommits, the extension signature will always be empty.
// Even if the signed over data is empty, we still add the signature
var extSig []byte
var nonRpExtSig []byte
if vote.Type == cmtproto.PrecommitType && !types.ProtoBlockIDIsNil(&vote.BlockID) {
extSignBytes := types.VoteExtensionSignBytes(chainID, vote)
extSignBytes, nonRpExtSignBytes := types.VoteExtensionSignBytes(chainID, vote)
extSig, err = pv.Key.PrivKey.Sign(extSignBytes)
if err != nil {
return err
}
} else if len(vote.Extension) > 0 {
nonRpExtSig, err = pv.Key.PrivKey.Sign(nonRpExtSignBytes)
if err != nil {
return err
}
} else if len(vote.Extension) > 0 || len(vote.NonRpExtension) > 0 {
return errors.New("unexpected vote extension - extensions are only allowed in non-nil precommits")
}

Expand All @@ -351,6 +356,7 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error {
}

vote.ExtensionSignature = extSig
vote.NonRpExtensionSignature = nonRpExtSig

return err
}
Expand All @@ -363,6 +369,7 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error {
pv.saveSigned(height, round, step, signBytes, sig)
vote.Signature = sig
vote.ExtensionSignature = extSig
vote.NonRpExtensionSignature = nonRpExtSig

return nil
}
Expand Down
Loading

0 comments on commit 809f7ba

Please sign in to comment.