Skip to content

Commit

Permalink
move verify double voting evidence to ut
Browse files Browse the repository at this point in the history
  • Loading branch information
sainoe committed Aug 24, 2023
1 parent 0b2665e commit 6e83b8f
Show file tree
Hide file tree
Showing 3 changed files with 336 additions and 315 deletions.
320 changes: 5 additions & 315 deletions tests/integration/double_vote.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package integration

import (
"time"

abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

sdk "github.com/cosmos/cosmos-sdk/types"
testutil "github.com/cosmos/interchain-security/v2/testutil/crypto"
"github.com/cosmos/interchain-security/v2/x/ccv/provider/types"
"github.com/tendermint/tendermint/crypto/tmhash"
tmtypes "github.com/tendermint/tendermint/types"
)

Expand All @@ -30,10 +25,10 @@ func (s *CCVTestSuite) TestHandleConsumerDoubleVoting() {
val := valSet.Validators[0]
signer := s.consumerChain.Signers[val.Address.String()]

blockID1 := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
blockID1 := testutil.MakeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
blockID2 := testutil.MakeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))

vote1 := makeAndSignVote(
vote1 := testutil.MakeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
Expand All @@ -42,7 +37,7 @@ func (s *CCVTestSuite) TestHandleConsumerDoubleVoting() {
s.consumerChain.ChainID,
)

badVote := makeAndSignVote(
badVote := testutil.MakeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
Expand Down Expand Up @@ -127,308 +122,3 @@ func (s *CCVTestSuite) TestHandleConsumerDoubleVoting() {
})
}
}

func (s *CCVTestSuite) TestVerifyDoubleVotingEvidence() {
s.SetupCCVChannel(s.path)
// required to have the consumer client revision height greater than 0
s.SendEmptyVSCPacket()

valSet, err := tmtypes.ValidatorSetFromProto(s.consumerChain.LastHeader.ValidatorSet)
s.Require().NoError(err)

val := valSet.Validators[0]
signer := s.consumerChain.Signers[val.Address.String()]
val2 := valSet.Validators[1]
signer2 := s.consumerChain.Signers[val2.Address.String()]

blockID1 := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))

oldTime := s.consumerCtx().BlockTime().Add(-505 * time.Hour)

consuAddr := types.NewConsumerConsAddress(sdk.ConsAddress(val.Address.Bytes()))
provAddr := s.providerApp.GetProviderKeeper().GetProviderAddrFromConsumerAddr(s.providerCtx(), s.consumerChain.ChainID, consuAddr)

testCases := []struct {
name string
votes []*tmtypes.Vote
chainID string
expPass bool
}{
{
"evidence is too old - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
oldTime,
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
oldTime,
valSet,
signer,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
false,
},
{
"evidence has votes with different block height - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight()+1,
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
false,
},
{
"evidence has votes with different validator address - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer2,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
false,
},
{
"evidence has votes with same block IDs - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
false,
},
{
"no consumer chain exists for the given chain ID - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
},
"WrongChainID",
false,
},
{
"voteA is signed using the wrong chain ID - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
"WrongChainID",
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
false,
},
{
"voteB is signed using the wrong chain ID - shouldn't pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
"WrongChainID",
),
},
s.consumerChain.ChainID,
false,
},
{
"valid double voting evidence should pass",
[]*tmtypes.Vote{
makeAndSignVote(
blockID1,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
makeAndSignVote(
blockID2,
s.consumerCtx().BlockHeight(),
s.consumerCtx().BlockTime(),
valSet,
signer,
s.consumerChain.ChainID,
),
},
s.consumerChain.ChainID,
true,
},
}

for _, tc := range testCases {
ctx := setDefaultConsensusEvidenceParams(s.providerCtx())
s.Run(tc.name, func() {
// get the consumer chain public key assigned to the validator
consuPubkey, ok := s.providerApp.GetProviderKeeper().GetValidatorConsumerPubKey(
ctx,
s.consumerChain.ChainID,
provAddr,
)
s.Require().True(ok)

err := s.providerApp.GetProviderKeeper().VerifyDoubleVotingEvidence(
ctx,
tmtypes.DuplicateVoteEvidence{
VoteA: tc.votes[0],
VoteB: tc.votes[1],
ValidatorPower: val.VotingPower,
TotalVotingPower: val.VotingPower,
Timestamp: tc.votes[0].Timestamp,
},
tc.chainID,
consuPubkey,
)
if tc.expPass {
s.Require().NoError(err)
} else {
s.Require().Error(err)
}
})
}
}

// utility function duplicated from CometBFT
// see https://github.com/cometbft/cometbft/blob/main/evidence/verify_test.go#L554
func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID {
var (
h = make([]byte, tmhash.Size)
psH = make([]byte, tmhash.Size)
)
copy(h, hash)
copy(psH, partSetHash)
return tmtypes.BlockID{
Hash: h,
PartSetHeader: tmtypes.PartSetHeader{
Total: partSetSize,
Hash: psH,
},
}
}

func makeAndSignVote(
blockID tmtypes.BlockID,
blockHeight int64,
blockTime time.Time,
valSet *tmtypes.ValidatorSet,
signer tmtypes.PrivValidator,
chainID string,
) *tmtypes.Vote {
vote, err := tmtypes.MakeVote(
blockHeight,
blockID,
valSet,
signer,
chainID,
blockTime,
)
if err != nil {
panic(err)
}

v := vote.ToProto()
err = signer.SignVote(chainID, v)
if err != nil {
panic(err)
}

vote.Signature = v.Signature
return vote
}

func setDefaultConsensusEvidenceParams(ctx sdk.Context) sdk.Context {
return ctx.WithConsensusParams(
&abci.ConsensusParams{
Evidence: &tmproto.EvidenceParams{
MaxAgeNumBlocks: 302400,
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
MaxBytes: 10000,
},
},
)
}
Loading

0 comments on commit 6e83b8f

Please sign in to comment.