gitlab.com/SiaPrime/SiaPrime@v1.4.1/node/api/transactionpool.go (about)

     1  package api
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"net/http"
     7  
     8  	"github.com/julienschmidt/httprouter"
     9  
    10  	"gitlab.com/SiaPrime/SiaPrime/crypto"
    11  	"gitlab.com/SiaPrime/SiaPrime/encoding"
    12  	"gitlab.com/SiaPrime/SiaPrime/modules"
    13  	"gitlab.com/SiaPrime/SiaPrime/types"
    14  )
    15  
    16  type (
    17  	// TpoolFeeGET contains the current estimated fee
    18  	TpoolFeeGET struct {
    19  		Minimum types.Currency `json:"minimum"`
    20  		Maximum types.Currency `json:"maximum"`
    21  	}
    22  
    23  	// TpoolRawGET contains the requested transaction encoded to the raw
    24  	// format, along with the id of that transaction.
    25  	TpoolRawGET struct {
    26  		ID          types.TransactionID `json:"id"`
    27  		Parents     []byte              `json:"parents"`
    28  		Transaction []byte              `json:"transaction"`
    29  	}
    30  
    31  	// TpoolConfirmedGET contains information about whether or not
    32  	// the transaction has been seen on the blockhain
    33  	TpoolConfirmedGET struct {
    34  		Confirmed bool `json:"confirmed"`
    35  	}
    36  )
    37  
    38  // decodeTransactionID will decode a transaction id from a string.
    39  func decodeTransactionID(txidStr string) (types.TransactionID, error) {
    40  	txid := new(crypto.Hash)
    41  	err := txid.LoadString(txidStr)
    42  	if err != nil {
    43  		return types.TransactionID{}, err
    44  	}
    45  	return types.TransactionID(*txid), nil
    46  }
    47  
    48  // tpoolFeeHandlerGET returns the current estimated fee. Transactions with
    49  // fees are lower than the estimated fee may take longer to confirm.
    50  func (api *API) tpoolFeeHandlerGET(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
    51  	min, max := api.tpool.FeeEstimation()
    52  	WriteJSON(w, TpoolFeeGET{
    53  		Minimum: min,
    54  		Maximum: max,
    55  	})
    56  }
    57  
    58  // tpoolRawHandlerGET will provide the raw byte representation of a
    59  // transaction that matches the input id.
    60  func (api *API) tpoolRawHandlerGET(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
    61  	txid, err := decodeTransactionID(ps.ByName("id"))
    62  	if err != nil {
    63  		WriteError(w, Error{"error decoding transaction id:" + err.Error()}, http.StatusBadRequest)
    64  		return
    65  	}
    66  	txn, parents, exists := api.tpool.Transaction(txid)
    67  	if !exists {
    68  		WriteError(w, Error{"transaction not found in transaction pool"}, http.StatusBadRequest)
    69  		return
    70  	}
    71  
    72  	WriteJSON(w, TpoolRawGET{
    73  		ID:          txid,
    74  		Parents:     encoding.Marshal(parents),
    75  		Transaction: encoding.Marshal(txn),
    76  	})
    77  }
    78  
    79  // tpoolRawHandlerPOST takes a raw encoded transaction set and posts
    80  // it to the transaction pool, relaying it to the transaction pool's peers
    81  // regardless of if the set is accepted.
    82  func (api *API) tpoolRawHandlerPOST(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
    83  	var parents []types.Transaction
    84  	var txn types.Transaction
    85  
    86  	// JSON, base64, and raw binary are accepted
    87  	if err := json.Unmarshal([]byte(req.FormValue("parents")), &parents); err != nil {
    88  		rawParents, err := base64.StdEncoding.DecodeString(req.FormValue("parents"))
    89  		if err != nil {
    90  			rawParents = []byte(req.FormValue("parents"))
    91  		}
    92  		if err := encoding.Unmarshal(rawParents, &parents); err != nil {
    93  			WriteError(w, Error{"error decoding parents:" + err.Error()}, http.StatusBadRequest)
    94  			return
    95  		}
    96  	}
    97  	if err := json.Unmarshal([]byte(req.FormValue("transaction")), &txn); err != nil {
    98  		rawTransaction, err := base64.StdEncoding.DecodeString(req.FormValue("transaction"))
    99  		if err != nil {
   100  			rawTransaction = []byte(req.FormValue("transaction"))
   101  		}
   102  		if err := encoding.Unmarshal(rawTransaction, &txn); err != nil {
   103  			WriteError(w, Error{"error decoding transaction:" + err.Error()}, http.StatusBadRequest)
   104  			return
   105  		}
   106  	}
   107  	// Broadcast the transaction set, so that they are passed to any peers that
   108  	// may have rejected them earlier.
   109  	txnSet := append(parents, txn)
   110  	api.tpool.Broadcast(txnSet)
   111  	err := api.tpool.AcceptTransactionSet(txnSet)
   112  	if err != nil && err != modules.ErrDuplicateTransactionSet {
   113  		WriteError(w, Error{"error accepting transaction set:" + err.Error()}, http.StatusBadRequest)
   114  		return
   115  	}
   116  	WriteSuccess(w)
   117  }
   118  
   119  // tpoolConfirmedGET returns whether the specified transaction has
   120  // been seen on the blockchain.
   121  func (api *API) tpoolConfirmedGET(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
   122  	txid, err := decodeTransactionID(ps.ByName("id"))
   123  	if err != nil {
   124  		WriteError(w, Error{"error decoding transaction id:" + err.Error()}, http.StatusBadRequest)
   125  		return
   126  	}
   127  	confirmed, err := api.tpool.TransactionConfirmed(txid)
   128  	if err != nil {
   129  		WriteError(w, Error{"error fetching transaction status:" + err.Error()}, http.StatusBadRequest)
   130  		return
   131  	}
   132  	WriteJSON(w, TpoolConfirmedGET{
   133  		Confirmed: confirmed,
   134  	})
   135  }