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