github.com/vipernet-xyz/tm@v0.34.24/types/tx_test.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	tmrand "github.com/vipernet-xyz/tm/libs/rand"
    11  	ctest "github.com/vipernet-xyz/tm/libs/test"
    12  	tmproto "github.com/vipernet-xyz/tm/proto/tendermint/types"
    13  )
    14  
    15  func makeTxs(cnt, size int) Txs {
    16  	txs := make(Txs, cnt)
    17  	for i := 0; i < cnt; i++ {
    18  		txs[i] = tmrand.Bytes(size)
    19  	}
    20  	return txs
    21  }
    22  
    23  func randInt(low, high int) int {
    24  	off := tmrand.Int() % (high - low)
    25  	return low + off
    26  }
    27  
    28  func TestTxIndex(t *testing.T) {
    29  	for i := 0; i < 20; i++ {
    30  		txs := makeTxs(15, 60)
    31  		for j := 0; j < len(txs); j++ {
    32  			tx := txs[j]
    33  			idx := txs.Index(tx)
    34  			assert.Equal(t, j, idx)
    35  		}
    36  		assert.Equal(t, -1, txs.Index(nil))
    37  		assert.Equal(t, -1, txs.Index(Tx("foodnwkf")))
    38  	}
    39  }
    40  
    41  func TestTxIndexByHash(t *testing.T) {
    42  	for i := 0; i < 20; i++ {
    43  		txs := makeTxs(15, 60)
    44  		for j := 0; j < len(txs); j++ {
    45  			tx := txs[j]
    46  			idx := txs.IndexByHash(tx.Hash())
    47  			assert.Equal(t, j, idx)
    48  		}
    49  		assert.Equal(t, -1, txs.IndexByHash(nil))
    50  		assert.Equal(t, -1, txs.IndexByHash(Tx("foodnwkf").Hash()))
    51  	}
    52  }
    53  
    54  func TestValidTxProof(t *testing.T) {
    55  	cases := []struct {
    56  		txs Txs
    57  	}{
    58  		{Txs{{1, 4, 34, 87, 163, 1}}},
    59  		{Txs{{5, 56, 165, 2}, {4, 77}}},
    60  		{Txs{Tx("foo"), Tx("bar"), Tx("baz")}},
    61  		{makeTxs(20, 5)},
    62  		{makeTxs(7, 81)},
    63  		{makeTxs(61, 15)},
    64  	}
    65  
    66  	for h, tc := range cases {
    67  		txs := tc.txs
    68  		root := txs.Hash()
    69  		// make sure valid proof for every tx
    70  		for i := range txs {
    71  			tx := []byte(txs[i])
    72  			proof := txs.Proof(i)
    73  			assert.EqualValues(t, i, proof.Proof.Index, "%d: %d", h, i)
    74  			assert.EqualValues(t, len(txs), proof.Proof.Total, "%d: %d", h, i)
    75  			assert.EqualValues(t, root, proof.RootHash, "%d: %d", h, i)
    76  			assert.EqualValues(t, tx, proof.Data, "%d: %d", h, i)
    77  			assert.EqualValues(t, txs[i].Hash(), proof.Leaf(), "%d: %d", h, i)
    78  			assert.Nil(t, proof.Validate(root), "%d: %d", h, i)
    79  			assert.NotNil(t, proof.Validate([]byte("foobar")), "%d: %d", h, i)
    80  
    81  			// read-write must also work
    82  			var (
    83  				p2  TxProof
    84  				pb2 tmproto.TxProof
    85  			)
    86  			pbProof := proof.ToProto()
    87  			bin, err := pbProof.Marshal()
    88  			require.NoError(t, err)
    89  
    90  			err = pb2.Unmarshal(bin)
    91  			require.NoError(t, err)
    92  
    93  			p2, err = TxProofFromProto(pb2)
    94  			if assert.Nil(t, err, "%d: %d: %+v", h, i, err) {
    95  				assert.Nil(t, p2.Validate(root), "%d: %d", h, i)
    96  			}
    97  		}
    98  	}
    99  }
   100  
   101  func TestTxProofUnchangable(t *testing.T) {
   102  	// run the other test a bunch...
   103  	for i := 0; i < 40; i++ {
   104  		testTxProofUnchangable(t)
   105  	}
   106  }
   107  
   108  func testTxProofUnchangable(t *testing.T) {
   109  	// make some proof
   110  	txs := makeTxs(randInt(2, 100), randInt(16, 128))
   111  	root := txs.Hash()
   112  	i := randInt(0, len(txs)-1)
   113  	proof := txs.Proof(i)
   114  
   115  	// make sure it is valid to start with
   116  	assert.Nil(t, proof.Validate(root))
   117  	pbProof := proof.ToProto()
   118  	bin, err := pbProof.Marshal()
   119  	require.NoError(t, err)
   120  
   121  	// try mutating the data and make sure nothing breaks
   122  	for j := 0; j < 500; j++ {
   123  		bad := ctest.MutateByteSlice(bin)
   124  		if !bytes.Equal(bad, bin) {
   125  			assertBadProof(t, root, bad, proof)
   126  		}
   127  	}
   128  }
   129  
   130  // This makes sure that the proof doesn't deserialize into something valid.
   131  func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) {
   132  
   133  	var (
   134  		proof   TxProof
   135  		pbProof tmproto.TxProof
   136  	)
   137  	err := pbProof.Unmarshal(bad)
   138  	if err == nil {
   139  		proof, err = TxProofFromProto(pbProof)
   140  		if err == nil {
   141  			err = proof.Validate(root)
   142  			if err == nil {
   143  				// XXX Fix simple merkle proofs so the following is *not* OK.
   144  				// This can happen if we have a slightly different total (where the
   145  				// path ends up the same). If it is something else, we have a real
   146  				// problem.
   147  				assert.NotEqual(t, proof.Proof.Total, good.Proof.Total, "bad: %#v\ngood: %#v", proof, good)
   148  			}
   149  		}
   150  	}
   151  }