github.com/aakash4dev/cometbft@v0.38.2/types/tx_test.go (about)

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