github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/rpc/client/evidence_test.go (about)

     1  package client_test
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	abci "github.com/franono/tendermint/abci/types"
    12  	"github.com/franono/tendermint/crypto"
    13  	"github.com/franono/tendermint/crypto/ed25519"
    14  	"github.com/franono/tendermint/crypto/tmhash"
    15  	"github.com/franono/tendermint/privval"
    16  	"github.com/franono/tendermint/rpc/client"
    17  	rpctest "github.com/franono/tendermint/rpc/test"
    18  	"github.com/franono/tendermint/types"
    19  )
    20  
    21  func newEvidence(t *testing.T, val *privval.FilePV,
    22  	vote *types.Vote, vote2 *types.Vote,
    23  	chainID string) *types.DuplicateVoteEvidence {
    24  
    25  	var err error
    26  	vote.Signature, err = val.Key.PrivKey.Sign(vote.SignBytes(chainID))
    27  	require.NoError(t, err)
    28  
    29  	vote2.Signature, err = val.Key.PrivKey.Sign(vote2.SignBytes(chainID))
    30  	require.NoError(t, err)
    31  
    32  	return types.NewDuplicateVoteEvidence(vote, vote2)
    33  }
    34  
    35  func makeEvidences(
    36  	t *testing.T,
    37  	val *privval.FilePV,
    38  	chainID string,
    39  ) (correct *types.DuplicateVoteEvidence, fakes []*types.DuplicateVoteEvidence) {
    40  	vote := types.Vote{
    41  		ValidatorAddress: val.Key.Address,
    42  		ValidatorIndex:   0,
    43  		Height:           1,
    44  		Round:            0,
    45  		Type:             types.PrevoteType,
    46  		Timestamp:        time.Now().UTC(),
    47  		BlockID: types.BlockID{
    48  			Hash: tmhash.Sum([]byte("blockhash")),
    49  			PartsHeader: types.PartSetHeader{
    50  				Total: 1000,
    51  				Hash:  tmhash.Sum([]byte("partset")),
    52  			},
    53  		},
    54  	}
    55  
    56  	vote2 := vote
    57  	vote2.BlockID.Hash = tmhash.Sum([]byte("blockhash2"))
    58  	correct = newEvidence(t, val, &vote, &vote2, chainID)
    59  
    60  	fakes = make([]*types.DuplicateVoteEvidence, 0)
    61  
    62  	// different address
    63  	{
    64  		v := vote2
    65  		v.ValidatorAddress = []byte("some_address")
    66  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
    67  	}
    68  
    69  	// different index
    70  	{
    71  		v := vote2
    72  		v.ValidatorIndex = vote.ValidatorIndex + 1
    73  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
    74  	}
    75  
    76  	// different height
    77  	{
    78  		v := vote2
    79  		v.Height = vote.Height + 1
    80  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
    81  	}
    82  
    83  	// different round
    84  	{
    85  		v := vote2
    86  		v.Round = vote.Round + 1
    87  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
    88  	}
    89  
    90  	// different type
    91  	{
    92  		v := vote2
    93  		v.Type = types.PrecommitType
    94  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
    95  	}
    96  
    97  	// exactly same vote
    98  	{
    99  		v := vote
   100  		fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID))
   101  	}
   102  
   103  	return correct, fakes
   104  }
   105  
   106  func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) {
   107  	var (
   108  		config  = rpctest.GetConfig()
   109  		chainID = config.ChainID()
   110  		pv      = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
   111  	)
   112  
   113  	correct, fakes := makeEvidences(t, pv, chainID)
   114  
   115  	for i, c := range GetClients() {
   116  		t.Logf("client %d", i)
   117  
   118  		result, err := c.BroadcastEvidence(correct)
   119  		require.NoError(t, err, "BroadcastEvidence(%s) failed", correct)
   120  		assert.Equal(t, correct.Hash(), result.Hash, "expected result hash to match evidence hash")
   121  
   122  		status, err := c.Status()
   123  		require.NoError(t, err)
   124  		client.WaitForHeight(c, status.SyncInfo.LatestBlockHeight+2, nil)
   125  
   126  		ed25519pub := pv.Key.PubKey.(ed25519.PubKeyEd25519)
   127  		rawpub := ed25519pub[:]
   128  		result2, err := c.ABCIQuery("/val", rawpub)
   129  		require.NoError(t, err)
   130  		qres := result2.Response
   131  		require.True(t, qres.IsOK())
   132  
   133  		var v abci.ValidatorUpdate
   134  		err = abci.ReadMessage(bytes.NewReader(qres.Value), &v)
   135  		require.NoError(t, err, "Error reading query result, value %v", qres.Value)
   136  
   137  		require.EqualValues(t, rawpub, v.PubKey.Data, "Stored PubKey not equal with expected, value %v", string(qres.Value))
   138  		require.Equal(t, int64(9), v.Power, "Stored Power not equal with expected, value %v", string(qres.Value))
   139  
   140  		for _, fake := range fakes {
   141  			_, err := c.BroadcastEvidence(fake)
   142  			require.Error(t, err, "BroadcastEvidence(%s) succeeded, but the evidence was fake", fake)
   143  		}
   144  	}
   145  }
   146  
   147  func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) {
   148  	var (
   149  		config  = rpctest.GetConfig()
   150  		chainID = config.ChainID()
   151  		pv      = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
   152  	)
   153  
   154  	for i, c := range GetClients() {
   155  		t.Logf("client %d", i)
   156  
   157  		h1, err := c.Commit(nil)
   158  		require.NoError(t, err)
   159  		require.NotNil(t, h1.SignedHeader.Header)
   160  
   161  		// Create an alternative header with a different AppHash.
   162  		h2 := &types.SignedHeader{
   163  			Header: &types.Header{
   164  				Version:            h1.Version,
   165  				ChainID:            h1.ChainID,
   166  				Height:             h1.Height,
   167  				Time:               h1.Time,
   168  				LastBlockID:        h1.LastBlockID,
   169  				LastCommitHash:     h1.LastCommitHash,
   170  				DataHash:           h1.DataHash,
   171  				ValidatorsHash:     h1.ValidatorsHash,
   172  				NextValidatorsHash: h1.NextValidatorsHash,
   173  				ConsensusHash:      h1.ConsensusHash,
   174  				AppHash:            crypto.CRandBytes(32),
   175  				LastResultsHash:    h1.LastResultsHash,
   176  				EvidenceHash:       h1.EvidenceHash,
   177  				ProposerAddress:    h1.ProposerAddress,
   178  			},
   179  			Commit: types.NewCommit(h1.Height, 1, h1.Commit.BlockID, h1.Commit.Signatures),
   180  		}
   181  		h2.Commit.BlockID = types.BlockID{
   182  			Hash:        h2.Hash(),
   183  			PartsHeader: types.PartSetHeader{Total: 1, Hash: crypto.CRandBytes(32)},
   184  		}
   185  		vote := &types.Vote{
   186  			ValidatorAddress: pv.Key.Address,
   187  			ValidatorIndex:   0,
   188  			Height:           h2.Height,
   189  			Round:            h2.Commit.Round,
   190  			Timestamp:        h2.Time,
   191  			Type:             types.PrecommitType,
   192  			BlockID:          h2.Commit.BlockID,
   193  		}
   194  		signBytes, err := pv.Key.PrivKey.Sign(vote.SignBytes(chainID))
   195  		require.NoError(t, err)
   196  		h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time)
   197  
   198  		t.Logf("h1 AppHash: %X", h1.AppHash)
   199  		t.Logf("h2 AppHash: %X", h2.AppHash)
   200  
   201  		ev := types.ConflictingHeadersEvidence{
   202  			H1: &h1.SignedHeader,
   203  			H2: h2,
   204  		}
   205  
   206  		result, err := c.BroadcastEvidence(ev)
   207  		require.NoError(t, err, "BroadcastEvidence(%s) failed", ev)
   208  		assert.Equal(t, ev.Hash(), result.Hash, "expected result hash to match evidence hash")
   209  	}
   210  }