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 }