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.

151 lines
3.7 KiB

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