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.

125 lines
3.0 KiB

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