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.

209 lines
5.6 KiB

7 years ago
  1. package core
  2. import (
  3. "fmt"
  4. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  5. "github.com/tendermint/tendermint/state/txindex/null"
  6. "github.com/tendermint/tendermint/types"
  7. tmquery "github.com/tendermint/tmlibs/pubsub/query"
  8. )
  9. // Tx allows you to query the transaction results. `nil` could mean the
  10. // transaction is in the mempool, invalidated, or was not sent in the first
  11. // place.
  12. //
  13. // ```shell
  14. // curl "localhost:46657/tx?hash=0x2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
  15. // ```
  16. //
  17. // ```go
  18. // client := client.NewHTTP("tcp://0.0.0.0:46657", "/websocket")
  19. // tx, err := client.Tx([]byte("2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"), true)
  20. // ```
  21. //
  22. // > The above command returns JSON structured like this:
  23. //
  24. // ```json
  25. // {
  26. // "error": "",
  27. // "result": {
  28. // "proof": {
  29. // "Proof": {
  30. // "aunts": []
  31. // },
  32. // "Data": "YWJjZA==",
  33. // "RootHash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF",
  34. // "Total": 1,
  35. // "Index": 0
  36. // },
  37. // "tx": "YWJjZA==",
  38. // "tx_result": {
  39. // "log": "",
  40. // "data": "",
  41. // "code": 0
  42. // },
  43. // "index": 0,
  44. // "height": 52,
  45. // "hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
  46. // },
  47. // "id": "",
  48. // "jsonrpc": "2.0"
  49. // }
  50. // ```
  51. //
  52. // Returns a transaction matching the given transaction hash.
  53. //
  54. // ### Query Parameters
  55. //
  56. // | Parameter | Type | Default | Required | Description |
  57. // |-----------+--------+---------+----------+-----------------------------------------------------------|
  58. // | hash | []byte | nil | true | The transaction hash |
  59. // | prove | bool | false | false | Include a proof of the transaction inclusion in the block |
  60. //
  61. // ### Returns
  62. //
  63. // - `proof`: the `types.TxProof` object
  64. // - `tx`: `[]byte` - the transaction
  65. // - `tx_result`: the `abci.Result` object
  66. // - `index`: `int` - index of the transaction
  67. // - `height`: `int` - height of the block where this transaction was in
  68. // - `hash`: `[]byte` - hash of the transaction
  69. func Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {
  70. // if index is disabled, return error
  71. if _, ok := txIndexer.(*null.TxIndex); ok {
  72. return nil, fmt.Errorf("Transaction indexing is disabled")
  73. }
  74. r, err := txIndexer.Get(hash)
  75. if err != nil {
  76. return nil, err
  77. }
  78. if r == nil {
  79. return nil, fmt.Errorf("Tx (%X) not found", hash)
  80. }
  81. height := r.Height
  82. index := r.Index
  83. var proof types.TxProof
  84. if prove {
  85. block := blockStore.LoadBlock(height)
  86. proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
  87. }
  88. return &ctypes.ResultTx{
  89. Hash: hash,
  90. Height: height,
  91. Index: uint32(index),
  92. TxResult: r.Result,
  93. Tx: r.Tx,
  94. Proof: proof,
  95. }, nil
  96. }
  97. // TxSearch allows you to query for multiple transactions results.
  98. //
  99. // ```shell
  100. // curl "localhost:46657/tx_search?query=\"account.owner='Ivan'\"&prove=true"
  101. // ```
  102. //
  103. // ```go
  104. // client := client.NewHTTP("tcp://0.0.0.0:46657", "/websocket")
  105. // q, err := tmquery.New("account.owner='Ivan'")
  106. // tx, err := client.TxSearch(q, true)
  107. // ```
  108. //
  109. // > The above command returns JSON structured like this:
  110. //
  111. // ```json
  112. // {
  113. // "result": [
  114. // {
  115. // "proof": {
  116. // "Proof": {
  117. // "aunts": [
  118. // "J3LHbizt806uKnABNLwG4l7gXCA=",
  119. // "iblMO/M1TnNtlAefJyNCeVhjAb0=",
  120. // "iVk3ryurVaEEhdeS0ohAJZ3wtB8=",
  121. // "5hqMkTeGqpct51ohX0lZLIdsn7Q=",
  122. // "afhsNxFnLlZgFDoyPpdQSe0bR8g="
  123. // ]
  124. // },
  125. // "Data": "mvZHHa7HhZ4aRT0xMDA=",
  126. // "RootHash": "F6541223AA46E428CB1070E9840D2C3DF3B6D776",
  127. // "Total": 32,
  128. // "Index": 31
  129. // },
  130. // "tx": "mvZHHa7HhZ4aRT0xMDA=",
  131. // "tx_result": {},
  132. // "index": 31,
  133. // "height": 12,
  134. // "hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
  135. // }
  136. // ],
  137. // "id": "",
  138. // "jsonrpc": "2.0"
  139. // }
  140. // ```
  141. //
  142. // Returns transactions matching the given query.
  143. //
  144. // ### Query Parameters
  145. //
  146. // | Parameter | Type | Default | Required | Description |
  147. // |-----------+--------+---------+----------+-----------------------------------------------------------|
  148. // | query | string | "" | true | Query |
  149. // | prove | bool | false | false | Include proofs of the transactions inclusion in the block |
  150. //
  151. // ### Returns
  152. //
  153. // - `proof`: the `types.TxProof` object
  154. // - `tx`: `[]byte` - the transaction
  155. // - `tx_result`: the `abci.Result` object
  156. // - `index`: `int` - index of the transaction
  157. // - `height`: `int` - height of the block where this transaction was in
  158. // - `hash`: `[]byte` - hash of the transaction
  159. func TxSearch(query string, prove bool) ([]*ctypes.ResultTx, error) {
  160. // if index is disabled, return error
  161. if _, ok := txIndexer.(*null.TxIndex); ok {
  162. return nil, fmt.Errorf("Transaction indexing is disabled")
  163. }
  164. q, err := tmquery.New(query)
  165. if err != nil {
  166. return nil, err
  167. }
  168. results, err := txIndexer.Search(q)
  169. if err != nil {
  170. return nil, err
  171. }
  172. // TODO: we may want to consider putting a maximum on this length and somehow
  173. // informing the user that things were truncated.
  174. apiResults := make([]*ctypes.ResultTx, len(results))
  175. var proof types.TxProof
  176. for i, r := range results {
  177. height := r.Height
  178. index := r.Index
  179. if prove {
  180. block := blockStore.LoadBlock(height)
  181. proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
  182. }
  183. apiResults[i] = &ctypes.ResultTx{
  184. Hash: r.Tx.Hash(),
  185. Height: height,
  186. Index: index,
  187. TxResult: r.Result,
  188. Tx: r.Tx,
  189. Proof: proof,
  190. }
  191. }
  192. return apiResults, nil
  193. }