You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.7 KiB

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