github.com/evdatsion/aphelion-dpos-bft@v0.32.1/rpc/core/tx.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  
     6  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
     7  
     8  	tmquery "github.com/evdatsion/aphelion-dpos-bft/libs/pubsub/query"
     9  	ctypes "github.com/evdatsion/aphelion-dpos-bft/rpc/core/types"
    10  	rpctypes "github.com/evdatsion/aphelion-dpos-bft/rpc/lib/types"
    11  	"github.com/evdatsion/aphelion-dpos-bft/state/txindex/null"
    12  	"github.com/evdatsion/aphelion-dpos-bft/types"
    13  )
    14  
    15  // Tx allows you to query the transaction results. `nil` could mean the
    16  // transaction is in the mempool, invalidated, or was not sent in the first
    17  // place.
    18  //
    19  // ```shell
    20  // curl "localhost:26657/tx?hash=0xF87370F68C82D9AC7201248ECA48CEC5F16FFEC99C461C1B2961341A2FE9C1C8"
    21  // ```
    22  //
    23  // ```go
    24  // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
    25  // err := client.Start()
    26  // if err != nil {
    27  //   // handle error
    28  // }
    29  // defer client.Stop()
    30  // hashBytes, err := hex.DecodeString("F87370F68C82D9AC7201248ECA48CEC5F16FFEC99C461C1B2961341A2FE9C1C8")
    31  // tx, err := client.Tx(hashBytes, true)
    32  // ```
    33  //
    34  // > The above command returns JSON structured like this:
    35  //
    36  // ```json
    37  // {
    38  // 	"error": "",
    39  // 	"result": {
    40  // 		"proof": {
    41  // 			"Proof": {
    42  // 				"aunts": []
    43  // 			},
    44  // 			"Data": "YWJjZA==",
    45  // 			"RootHash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF",
    46  // 			"Total": "1",
    47  // 			"Index": "0"
    48  // 		},
    49  // 		"tx": "YWJjZA==",
    50  // 		"tx_result": {
    51  // 			"log": "",
    52  // 			"data": "",
    53  // 			"code": "0"
    54  // 		},
    55  // 		"index": "0",
    56  // 		"height": "52",
    57  //		"hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
    58  // 	},
    59  // 	"id": "",
    60  // 	"jsonrpc": "2.0"
    61  // }
    62  // ```
    63  //
    64  // Returns a transaction matching the given transaction hash.
    65  //
    66  // ### Query Parameters
    67  //
    68  // | Parameter | Type   | Default | Required | Description                                               |
    69  // |-----------+--------+---------+----------+-----------------------------------------------------------|
    70  // | hash      | []byte | nil     | true     | The transaction hash                                      |
    71  // | prove     | bool   | false   | false    | Include a proof of the transaction inclusion in the block |
    72  //
    73  // ### Returns
    74  //
    75  // - `proof`: the `types.TxProof` object
    76  // - `tx`: `[]byte` - the transaction
    77  // - `tx_result`: the `abci.Result` object
    78  // - `index`: `int` - index of the transaction
    79  // - `height`: `int` - height of the block where this transaction was in
    80  // - `hash`: `[]byte` - hash of the transaction
    81  func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
    82  
    83  	// if index is disabled, return error
    84  	if _, ok := txIndexer.(*null.TxIndex); ok {
    85  		return nil, fmt.Errorf("Transaction indexing is disabled")
    86  	}
    87  
    88  	r, err := txIndexer.Get(hash)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	if r == nil {
    94  		return nil, fmt.Errorf("Tx (%X) not found", hash)
    95  	}
    96  
    97  	height := r.Height
    98  	index := r.Index
    99  
   100  	var proof types.TxProof
   101  	if prove {
   102  		block := blockStore.LoadBlock(height)
   103  		proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
   104  	}
   105  
   106  	return &ctypes.ResultTx{
   107  		Hash:     hash,
   108  		Height:   height,
   109  		Index:    uint32(index),
   110  		TxResult: r.Result,
   111  		Tx:       r.Tx,
   112  		Proof:    proof,
   113  	}, nil
   114  }
   115  
   116  // TxSearch allows you to query for multiple transactions results. It returns a
   117  // list of transactions (maximum ?per_page entries) and the total count.
   118  //
   119  // ```shell
   120  // curl "localhost:26657/tx_search?query=\"account.owner='Ivan'\"&prove=true"
   121  // ```
   122  //
   123  // ```go
   124  // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
   125  // err := client.Start()
   126  // if err != nil {
   127  //   // handle error
   128  // }
   129  // defer client.Stop()
   130  // q, err := tmquery.New("account.owner='Ivan'")
   131  // tx, err := client.TxSearch(q, true)
   132  // ```
   133  //
   134  // > The above command returns JSON structured like this:
   135  //
   136  // ```json
   137  // {
   138  //   "jsonrpc": "2.0",
   139  //   "id": "",
   140  //   "result": {
   141  // 	   "txs": [
   142  //       {
   143  //         "proof": {
   144  //           "Proof": {
   145  //             "aunts": [
   146  //               "J3LHbizt806uKnABNLwG4l7gXCA=",
   147  //               "iblMO/M1TnNtlAefJyNCeVhjAb0=",
   148  //               "iVk3ryurVaEEhdeS0ohAJZ3wtB8=",
   149  //               "5hqMkTeGqpct51ohX0lZLIdsn7Q=",
   150  //               "afhsNxFnLlZgFDoyPpdQSe0bR8g="
   151  //             ]
   152  //           },
   153  //           "Data": "mvZHHa7HhZ4aRT0xMDA=",
   154  //           "RootHash": "F6541223AA46E428CB1070E9840D2C3DF3B6D776",
   155  //           "Total": "32",
   156  //           "Index": "31"
   157  //         },
   158  //         "tx": "mvZHHa7HhZ4aRT0xMDA=",
   159  //         "tx_result": {},
   160  //         "index": "31",
   161  //         "height": "12",
   162  //         "hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
   163  //       }
   164  //     ],
   165  //     "total_count": "1"
   166  //   }
   167  // }
   168  // ```
   169  //
   170  // ### Query Parameters
   171  //
   172  // | Parameter | Type   | Default | Required | Description                                               |
   173  // |-----------+--------+---------+----------+-----------------------------------------------------------|
   174  // | query     | string | ""      | true     | Query                                                     |
   175  // | prove     | bool   | false   | false    | Include proofs of the transactions inclusion in the block |
   176  // | page      | int    | 1       | false    | Page number (1-based)                                     |
   177  // | per_page  | int    | 30      | false    | Number of entries per page (max: 100)                     |
   178  //
   179  // ### Returns
   180  //
   181  // - `proof`: the `types.TxProof` object
   182  // - `tx`: `[]byte` - the transaction
   183  // - `tx_result`: the `abci.Result` object
   184  // - `index`: `int` - index of the transaction
   185  // - `height`: `int` - height of the block where this transaction was in
   186  // - `hash`: `[]byte` - hash of the transaction
   187  func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) {
   188  	// if index is disabled, return error
   189  	if _, ok := txIndexer.(*null.TxIndex); ok {
   190  		return nil, fmt.Errorf("Transaction indexing is disabled")
   191  	}
   192  
   193  	q, err := tmquery.New(query)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	results, err := txIndexer.Search(q)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  
   203  	totalCount := len(results)
   204  	perPage = validatePerPage(perPage)
   205  	page = validatePage(page, perPage, totalCount)
   206  	skipCount := validateSkipCount(page, perPage)
   207  
   208  	apiResults := make([]*ctypes.ResultTx, cmn.MinInt(perPage, totalCount-skipCount))
   209  	var proof types.TxProof
   210  	// if there's no tx in the results array, we don't need to loop through the apiResults array
   211  	for i := 0; i < len(apiResults); i++ {
   212  		r := results[skipCount+i]
   213  		height := r.Height
   214  		index := r.Index
   215  
   216  		if prove {
   217  			block := blockStore.LoadBlock(height)
   218  			proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
   219  		}
   220  
   221  		apiResults[i] = &ctypes.ResultTx{
   222  			Hash:     r.Tx.Hash(),
   223  			Height:   height,
   224  			Index:    index,
   225  			TxResult: r.Result,
   226  			Tx:       r.Tx,
   227  			Proof:    proof,
   228  		}
   229  	}
   230  
   231  	return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
   232  }