package client_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
tmrand "github.com/tendermint/tendermint/libs/rand"
|
|
"github.com/tendermint/tendermint/privval"
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
"github.com/tendermint/tendermint/rpc/client"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
// For some reason the empty node used in tests has a time of
|
|
// 2018-10-10 08:20:13.695936996 +0000 UTC
|
|
// this is because the test genesis time is set here
|
|
// so in order to validate evidence we need evidence to be the same time
|
|
var defaultTestTime = time.Date(2018, 10, 10, 8, 20, 13, 695936996, time.UTC)
|
|
|
|
func newEvidence(t *testing.T, val *privval.FilePV,
|
|
vote *types.Vote, vote2 *types.Vote,
|
|
chainID string) *types.DuplicateVoteEvidence {
|
|
t.Helper()
|
|
var err error
|
|
|
|
v := vote.ToProto()
|
|
v2 := vote2.ToProto()
|
|
|
|
vote.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v))
|
|
require.NoError(t, err)
|
|
|
|
vote2.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2))
|
|
require.NoError(t, err)
|
|
|
|
validator := types.NewValidator(val.Key.PubKey, 10)
|
|
valSet := types.NewValidatorSet([]*types.Validator{validator})
|
|
|
|
ev, err := types.NewDuplicateVoteEvidence(vote, vote2, defaultTestTime, valSet)
|
|
require.NoError(t, err)
|
|
return ev
|
|
}
|
|
|
|
func makeEvidences(
|
|
t *testing.T,
|
|
val *privval.FilePV,
|
|
chainID string,
|
|
) (correct *types.DuplicateVoteEvidence, fakes []*types.DuplicateVoteEvidence) {
|
|
vote := types.Vote{
|
|
ValidatorAddress: val.Key.Address,
|
|
ValidatorIndex: 0,
|
|
Height: 1,
|
|
Round: 0,
|
|
Type: tmproto.PrevoteType,
|
|
Timestamp: defaultTestTime,
|
|
BlockID: types.BlockID{
|
|
Hash: tmhash.Sum(tmrand.Bytes(tmhash.Size)),
|
|
PartSetHeader: types.PartSetHeader{
|
|
Total: 1000,
|
|
Hash: tmhash.Sum([]byte("partset")),
|
|
},
|
|
},
|
|
}
|
|
|
|
vote2 := vote
|
|
vote2.BlockID.Hash = tmhash.Sum([]byte("blockhash2"))
|
|
correct = newEvidence(t, val, &vote, &vote2, chainID)
|
|
|
|
fakes = make([]*types.DuplicateVoteEvidence, 0)
|
|
|
|
// different address
|
|
{
|
|
v := vote2
|
|
v.ValidatorAddress = []byte("some_address")
|
|
fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
|
|
}
|
|
|
|
// different height
|
|
{
|
|
v := vote2
|
|
v.Height = vote.Height + 1
|
|
fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
|
|
}
|
|
|
|
// different round
|
|
{
|
|
v := vote2
|
|
v.Round = vote.Round + 1
|
|
fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
|
|
}
|
|
|
|
// different type
|
|
{
|
|
v := vote2
|
|
v.Type = tmproto.PrecommitType
|
|
fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
|
|
}
|
|
|
|
// exactly same vote
|
|
{
|
|
v := vote
|
|
fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
|
|
}
|
|
|
|
return correct, fakes
|
|
}
|
|
|
|
func waitForBlock(ctx context.Context, t *testing.T, c client.Client, height int64) {
|
|
timer := time.NewTimer(0 * time.Millisecond)
|
|
defer timer.Stop()
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-timer.C:
|
|
status, err := c.Status(ctx)
|
|
require.NoError(t, err)
|
|
if status.SyncInfo.LatestBlockHeight >= height {
|
|
return
|
|
}
|
|
timer.Reset(200 * time.Millisecond)
|
|
}
|
|
}
|
|
}
|