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.

306 lines
7.3 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "math/rand"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. abci "github.com/tendermint/tendermint/abci/types"
  9. ctest "github.com/tendermint/tendermint/internal/libs/test"
  10. tmrand "github.com/tendermint/tendermint/libs/rand"
  11. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  12. )
  13. func makeTxs(cnt, size int) Txs {
  14. txs := make(Txs, cnt)
  15. for i := 0; i < cnt; i++ {
  16. txs[i] = tmrand.Bytes(size)
  17. }
  18. return txs
  19. }
  20. func TestTxIndex(t *testing.T) {
  21. for i := 0; i < 20; i++ {
  22. txs := makeTxs(15, 60)
  23. for j := 0; j < len(txs); j++ {
  24. tx := txs[j]
  25. idx := txs.Index(tx)
  26. assert.Equal(t, j, idx)
  27. }
  28. assert.Equal(t, -1, txs.Index(nil))
  29. assert.Equal(t, -1, txs.Index(Tx("foodnwkf")))
  30. }
  31. }
  32. func TestTxIndexByHash(t *testing.T) {
  33. for i := 0; i < 20; i++ {
  34. txs := makeTxs(15, 60)
  35. for j := 0; j < len(txs); j++ {
  36. tx := txs[j]
  37. idx := txs.IndexByHash(tx.Hash())
  38. assert.Equal(t, j, idx)
  39. }
  40. assert.Equal(t, -1, txs.IndexByHash(nil))
  41. assert.Equal(t, -1, txs.IndexByHash(Tx("foodnwkf").Hash()))
  42. }
  43. }
  44. func TestValidateTxRecordSet(t *testing.T) {
  45. t.Run("should error on total transaction size exceeding max data size", func(t *testing.T) {
  46. trs := []*abci.TxRecord{
  47. {
  48. Action: abci.TxRecord_ADDED,
  49. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  50. },
  51. {
  52. Action: abci.TxRecord_ADDED,
  53. Tx: Tx([]byte{6, 7, 8, 9, 10}),
  54. },
  55. }
  56. txrSet := NewTxRecordSet(trs)
  57. err := txrSet.Validate(9, []Tx{})
  58. require.Error(t, err)
  59. })
  60. t.Run("should error on duplicate transactions with the same action", func(t *testing.T) {
  61. trs := []*abci.TxRecord{
  62. {
  63. Action: abci.TxRecord_ADDED,
  64. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  65. },
  66. {
  67. Action: abci.TxRecord_ADDED,
  68. Tx: Tx([]byte{100}),
  69. },
  70. {
  71. Action: abci.TxRecord_ADDED,
  72. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  73. },
  74. {
  75. Action: abci.TxRecord_ADDED,
  76. Tx: Tx([]byte{200}),
  77. },
  78. }
  79. txrSet := NewTxRecordSet(trs)
  80. err := txrSet.Validate(100, []Tx{})
  81. require.Error(t, err)
  82. })
  83. t.Run("should error on duplicate transactions with mixed actions", func(t *testing.T) {
  84. trs := []*abci.TxRecord{
  85. {
  86. Action: abci.TxRecord_ADDED,
  87. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  88. },
  89. {
  90. Action: abci.TxRecord_ADDED,
  91. Tx: Tx([]byte{100}),
  92. },
  93. {
  94. Action: abci.TxRecord_REMOVED,
  95. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  96. },
  97. {
  98. Action: abci.TxRecord_ADDED,
  99. Tx: Tx([]byte{200}),
  100. },
  101. }
  102. txrSet := NewTxRecordSet(trs)
  103. err := txrSet.Validate(100, []Tx{})
  104. require.Error(t, err)
  105. })
  106. t.Run("should error on new transactions marked UNMODIFIED", func(t *testing.T) {
  107. trs := []*abci.TxRecord{
  108. {
  109. Action: abci.TxRecord_UNMODIFIED,
  110. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  111. },
  112. }
  113. txrSet := NewTxRecordSet(trs)
  114. err := txrSet.Validate(100, []Tx{})
  115. require.Error(t, err)
  116. })
  117. t.Run("should error on new transactions marked REMOVED", func(t *testing.T) {
  118. trs := []*abci.TxRecord{
  119. {
  120. Action: abci.TxRecord_REMOVED,
  121. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  122. },
  123. }
  124. txrSet := NewTxRecordSet(trs)
  125. err := txrSet.Validate(100, []Tx{})
  126. require.Error(t, err)
  127. })
  128. t.Run("should error on existing transaction marked as ADDED", func(t *testing.T) {
  129. trs := []*abci.TxRecord{
  130. {
  131. Action: abci.TxRecord_ADDED,
  132. Tx: Tx([]byte{5, 4, 3, 2, 1}),
  133. },
  134. {
  135. Action: abci.TxRecord_ADDED,
  136. Tx: Tx([]byte{6}),
  137. },
  138. {
  139. Action: abci.TxRecord_ADDED,
  140. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  141. },
  142. }
  143. txrSet := NewTxRecordSet(trs)
  144. err := txrSet.Validate(100, []Tx{{0}, {1, 2, 3, 4, 5}})
  145. require.Error(t, err)
  146. })
  147. t.Run("should error if any transaction marked as UNKNOWN", func(t *testing.T) {
  148. trs := []*abci.TxRecord{
  149. {
  150. Action: abci.TxRecord_UNKNOWN,
  151. Tx: Tx([]byte{1, 2, 3, 4, 5}),
  152. },
  153. }
  154. txrSet := NewTxRecordSet(trs)
  155. err := txrSet.Validate(100, []Tx{})
  156. require.Error(t, err)
  157. })
  158. t.Run("TxRecordSet preserves order", func(t *testing.T) {
  159. trs := []*abci.TxRecord{
  160. {
  161. Action: abci.TxRecord_ADDED,
  162. Tx: Tx([]byte{100}),
  163. },
  164. {
  165. Action: abci.TxRecord_ADDED,
  166. Tx: Tx([]byte{99}),
  167. },
  168. {
  169. Action: abci.TxRecord_ADDED,
  170. Tx: Tx([]byte{55}),
  171. },
  172. {
  173. Action: abci.TxRecord_ADDED,
  174. Tx: Tx([]byte{12}),
  175. },
  176. {
  177. Action: abci.TxRecord_ADDED,
  178. Tx: Tx([]byte{66}),
  179. },
  180. {
  181. Action: abci.TxRecord_ADDED,
  182. Tx: Tx([]byte{9}),
  183. },
  184. {
  185. Action: abci.TxRecord_ADDED,
  186. Tx: Tx([]byte{17}),
  187. },
  188. }
  189. txrSet := NewTxRecordSet(trs)
  190. err := txrSet.Validate(100, []Tx{})
  191. require.NoError(t, err)
  192. for i, tx := range txrSet.IncludedTxs() {
  193. require.Equal(t, Tx(trs[i].Tx), tx)
  194. }
  195. })
  196. }
  197. func TestValidTxProof(t *testing.T) {
  198. cases := []struct {
  199. txs Txs
  200. }{
  201. {Txs{{1, 4, 34, 87, 163, 1}}},
  202. {Txs{{5, 56, 165, 2}, {4, 77}}},
  203. {Txs{Tx("foo"), Tx("bar"), Tx("baz")}},
  204. {makeTxs(20, 5)},
  205. {makeTxs(7, 81)},
  206. {makeTxs(61, 15)},
  207. }
  208. for h, tc := range cases {
  209. txs := tc.txs
  210. root := txs.Hash()
  211. // make sure valid proof for every tx
  212. for i := range txs {
  213. tx := []byte(txs[i])
  214. proof := txs.Proof(i)
  215. assert.EqualValues(t, i, proof.Proof.Index, "%d: %d", h, i)
  216. assert.EqualValues(t, len(txs), proof.Proof.Total, "%d: %d", h, i)
  217. assert.EqualValues(t, root, proof.RootHash, "%d: %d", h, i)
  218. assert.EqualValues(t, tx, proof.Data, "%d: %d", h, i)
  219. assert.EqualValues(t, txs[i].Hash(), proof.Leaf(), "%d: %d", h, i)
  220. assert.Nil(t, proof.Validate(root), "%d: %d", h, i)
  221. assert.NotNil(t, proof.Validate([]byte("foobar")), "%d: %d", h, i)
  222. // read-write must also work
  223. var (
  224. p2 TxProof
  225. pb2 tmproto.TxProof
  226. )
  227. pbProof := proof.ToProto()
  228. bin, err := pbProof.Marshal()
  229. require.NoError(t, err)
  230. err = pb2.Unmarshal(bin)
  231. require.NoError(t, err)
  232. p2, err = TxProofFromProto(pb2)
  233. if assert.NoError(t, err, "%d: %d: %+v", h, i, err) {
  234. assert.Nil(t, p2.Validate(root), "%d: %d", h, i)
  235. }
  236. }
  237. }
  238. }
  239. func TestTxProofUnchangable(t *testing.T) {
  240. // run the other test a bunch...
  241. for i := 0; i < 40; i++ {
  242. testTxProofUnchangable(t)
  243. }
  244. }
  245. func testTxProofUnchangable(t *testing.T) {
  246. // make some proof
  247. txs := makeTxs(randInt(2, 100), randInt(16, 128))
  248. root := txs.Hash()
  249. i := randInt(0, len(txs)-1)
  250. proof := txs.Proof(i)
  251. // make sure it is valid to start with
  252. assert.Nil(t, proof.Validate(root))
  253. pbProof := proof.ToProto()
  254. bin, err := pbProof.Marshal()
  255. require.NoError(t, err)
  256. // try mutating the data and make sure nothing breaks
  257. for j := 0; j < 500; j++ {
  258. bad := ctest.MutateByteSlice(bin)
  259. if !bytes.Equal(bad, bin) {
  260. assertBadProof(t, root, bad, proof)
  261. }
  262. }
  263. }
  264. // This makes sure that the proof doesn't deserialize into something valid.
  265. func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) {
  266. var (
  267. proof TxProof
  268. pbProof tmproto.TxProof
  269. )
  270. err := pbProof.Unmarshal(bad)
  271. if err == nil {
  272. proof, err = TxProofFromProto(pbProof)
  273. if err == nil {
  274. err = proof.Validate(root)
  275. if err == nil {
  276. // XXX Fix simple merkle proofs so the following is *not* OK.
  277. // This can happen if we have a slightly different total (where the
  278. // path ends up the same). If it is something else, we have a real
  279. // problem.
  280. assert.NotEqual(t, proof.Proof.Total, good.Proof.Total, "bad: %#v\ngood: %#v", proof, good)
  281. }
  282. }
  283. }
  284. }
  285. func randInt(low, high int) int {
  286. return rand.Intn(high-low) + low
  287. }