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.

113 lines
2.8 KiB

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