github.com/vipernet-xyz/tendermint-core@v0.32.0/types/tx_test.go (about)

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