From ed435f7df56e96f06b855f7725436e259eae7420 Mon Sep 17 00:00:00 2001 From: Angelo Capossele <angelocapossele@gmail.com> Date: Wed, 15 Jan 2020 09:09:28 +0000 Subject: [PATCH] Adds a HTTP API to query and create transactions (#95) * :art: moves all webapi into one * :art: adds public key log * :art: changes txRequest to getTrytes * :art: rename packages * :pencil: adds comments * :art: changes status to error * :recycle: removes duration from API - getTrytes converts trits to trytes - set default spammer TPS to 1 Fix: Allow starting a node with gossip disabled (#97) * fix: remove selection flag and use gossip plugin * Upgrade hive.go feat: improve logging feat: improve analysis status chore: remove unused packages (#99) Fix: Use docker specific config (#100) * Use docker specific config * Format JSON :heavy_minus_sign: removes status :art: adds omitempty :lipstick: updates style import :sparkles: adds getNeighbors API :sparkles: adds getTransaction :heavy_minus_sign: removes addEndpoint * :construction: WIP * :construction: WIP * :sparkles: adds txs per address * :sparkles: adds findTransactions API --- main.go | 19 +-- packages/model/value_transaction/constants.go | 2 +- plugins/autopeering/autopeering.go | 1 + plugins/tangle/tx_per_address.go | 1 - plugins/ui/ui.go | 10 +- plugins/webapi-tx-request/plugin.go | 66 ----------- plugins/webapi/api.go | 9 -- .../broadcastData}/plugin.go | 57 +++++---- plugins/webapi/findTransactions/plugin.go | 67 +++++++++++ plugins/webapi/getNeighbors/plugin.go | 112 ++++++++++++++++++ plugins/webapi/getTransactions/plugin.go | 100 ++++++++++++++++ plugins/webapi/getTrytes/plugin.go | 77 ++++++++++++ .../{webapi-gtta => webapi/gtta}/plugin.go | 10 +- .../spammer}/plugin.go | 22 ++-- plugins/webauth/webauth.go | 2 +- 15 files changed, 419 insertions(+), 136 deletions(-) delete mode 100644 plugins/webapi-tx-request/plugin.go delete mode 100644 plugins/webapi/api.go rename plugins/{webapi-send-data => webapi/broadcastData}/plugin.go (55%) create mode 100644 plugins/webapi/findTransactions/plugin.go create mode 100644 plugins/webapi/getNeighbors/plugin.go create mode 100644 plugins/webapi/getTransactions/plugin.go create mode 100644 plugins/webapi/getTrytes/plugin.go rename plugins/{webapi-gtta => webapi/gtta}/plugin.go (68%) rename plugins/{webapi-spammer => webapi/spammer}/plugin.go (67%) diff --git a/main.go b/main.go index 14c100a8..7822849a 100644 --- a/main.go +++ b/main.go @@ -19,10 +19,13 @@ import ( "github.com/iotaledger/goshimmer/plugins/tipselection" "github.com/iotaledger/goshimmer/plugins/ui" "github.com/iotaledger/goshimmer/plugins/webapi" - webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi-gtta" - webapi_send_data "github.com/iotaledger/goshimmer/plugins/webapi-send-data" - webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi-spammer" - webapi_tx_request "github.com/iotaledger/goshimmer/plugins/webapi-tx-request" + webapi_broadcastData "github.com/iotaledger/goshimmer/plugins/webapi/broadcastData" + webapi_findTransactions "github.com/iotaledger/goshimmer/plugins/webapi/findTransactions" + webapi_getNeighbors "github.com/iotaledger/goshimmer/plugins/webapi/getNeighbors" + webapi_getTransactions "github.com/iotaledger/goshimmer/plugins/webapi/getTransactions" + webapi_getTrytes "github.com/iotaledger/goshimmer/plugins/webapi/getTrytes" + webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta" + webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer" "github.com/iotaledger/goshimmer/plugins/webauth" "github.com/iotaledger/goshimmer/plugins/zeromq" "github.com/iotaledger/hive.go/node" @@ -53,9 +56,11 @@ func main() { webapi.PLUGIN, webapi_gtta.PLUGIN, webapi_spammer.PLUGIN, - webapi_send_data.PLUGIN, - webapi_tx_request.PLUGIN, - webapi_spammer.PLUGIN, + webapi_broadcastData.PLUGIN, + webapi_getTrytes.PLUGIN, + webapi_getTransactions.PLUGIN, + webapi_findTransactions.PLUGIN, + webapi_getNeighbors.PLUGIN, ui.PLUGIN, webauth.PLUGIN, diff --git a/packages/model/value_transaction/constants.go b/packages/model/value_transaction/constants.go index c602d1ea..06a4c749 100644 --- a/packages/model/value_transaction/constants.go +++ b/packages/model/value_transaction/constants.go @@ -10,7 +10,7 @@ const ( ADDRESS_OFFSET = 0 VALUE_OFFSET = ADDRESS_END TIMESTAMP_OFFSET = VALUE_END - SIGNATURE_MESSAGE_FRAGMENT_OFFSET = TIMESTAMP_SIZE + SIGNATURE_MESSAGE_FRAGMENT_OFFSET = TIMESTAMP_END ADDRESS_SIZE = 243 VALUE_SIZE = 81 diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go index 474fe2bd..95b2b8e4 100644 --- a/plugins/autopeering/autopeering.go +++ b/plugins/autopeering/autopeering.go @@ -100,6 +100,7 @@ func start(shutdownSignal <-chan struct{}) { } log.Infof("Auto Peering started: address=%s", srv.LocalAddr()) + log.Debugf("Auto Peering server started: PubKey=%s", base64.StdEncoding.EncodeToString(local.GetInstance().PublicKey())) <-shutdownSignal log.Info("Stopping Auto Peering server ...") diff --git a/plugins/tangle/tx_per_address.go b/plugins/tangle/tx_per_address.go index c344aeda..c6bb03cd 100644 --- a/plugins/tangle/tx_per_address.go +++ b/plugins/tangle/tx_per_address.go @@ -30,7 +30,6 @@ func StoreTransactionHashForAddressInDatabase(address *TxHashForAddress) error { ); err != nil { return ErrDatabaseError.Derive(err, "failed to store tx for address in database") } - return nil } diff --git a/plugins/ui/ui.go b/plugins/ui/ui.go index f4458e58..9d9b8b1c 100644 --- a/plugins/ui/ui.go +++ b/plugins/ui/ui.go @@ -20,18 +20,18 @@ import ( func configure(plugin *node.Plugin) { //webapi.Server.Static("ui", "plugins/ui/src") - webapi.AddEndpoint("ui", func(c echo.Context) error { + webapi.Server.GET("ui", func(c echo.Context) error { return c.HTML(http.StatusOK, files["index.html"]) }) - webapi.AddEndpoint("ui/**", staticFileServer) + webapi.Server.GET("ui/**", staticFileServer) - webapi.AddEndpoint("ws", upgrader) - webapi.AddEndpoint("loghistory", func(c echo.Context) error { + webapi.Server.GET("ws", upgrader) + webapi.Server.GET("loghistory", func(c echo.Context) error { logMutex.RLock() defer logMutex.RUnlock() return c.JSON(http.StatusOK, logHistory) }) - webapi.AddEndpoint("tpsqueue", func(c echo.Context) error { + webapi.Server.GET("tpsqueue", func(c echo.Context) error { tpsQueueMutex.RLock() defer tpsQueueMutex.RUnlock() return c.JSON(http.StatusOK, tpsQueue) diff --git a/plugins/webapi-tx-request/plugin.go b/plugins/webapi-tx-request/plugin.go deleted file mode 100644 index 5f4e4282..00000000 --- a/plugins/webapi-tx-request/plugin.go +++ /dev/null @@ -1,66 +0,0 @@ -package webapi_tx_request - -import ( - "net/http" - "time" - - "github.com/iotaledger/goshimmer/plugins/tangle" - "github.com/iotaledger/goshimmer/plugins/webapi" - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/hive.go/node" - "github.com/labstack/echo" -) - -var PLUGIN = node.NewPlugin("WebAPI Transaction Request Endpoint", node.Enabled, configure) -var log *logger.Logger - -func configure(plugin *node.Plugin) { - log = logger.NewLogger("API-TxRequest") - webapi.AddEndpoint("txRequest", Handler) -} - -func Handler(c echo.Context) error { - c.Set("requestStartTime", time.Now()) - - var request webRequest - if err := c.Bind(&request); err != nil { - log.Info(err.Error()) - return requestFailed(c, err.Error()) - } - log.Info("Received:", request.TransactionHash) - - tx, err := tangle.GetTransaction(request.TransactionHash) - if err != nil { - return requestFailed(c, err.Error()) - } - if tx == nil { - return requestFailed(c, "Tx not found") - } - - return requestSuccessful(c, tx.GetBytes()) -} - -func requestSuccessful(c echo.Context, tx []byte) error { - return c.JSON(http.StatusOK, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - Transaction: tx, - Status: "OK", - }) -} - -func requestFailed(c echo.Context, message string) error { - return c.JSON(http.StatusNotFound, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - Status: message, - }) -} - -type webResponse struct { - Duration int64 `json:"duration"` - Transaction []byte `json:"transaction"` - Status string `json:"status"` -} - -type webRequest struct { - TransactionHash string `json:"transactionHash"` -} diff --git a/plugins/webapi/api.go b/plugins/webapi/api.go deleted file mode 100644 index 5c50d71b..00000000 --- a/plugins/webapi/api.go +++ /dev/null @@ -1,9 +0,0 @@ -package webapi - -import ( - "github.com/labstack/echo" -) - -func AddEndpoint(url string, handler func(c echo.Context) error) { - Server.GET(url, handler) -} diff --git a/plugins/webapi-send-data/plugin.go b/plugins/webapi/broadcastData/plugin.go similarity index 55% rename from plugins/webapi-send-data/plugin.go rename to plugins/webapi/broadcastData/plugin.go index c7029181..ef857882 100644 --- a/plugins/webapi-send-data/plugin.go +++ b/plugins/webapi/broadcastData/plugin.go @@ -1,62 +1,74 @@ -package webapi_send_data +package broadcastData import ( "net/http" "time" - "github.com/iotaledger/goshimmer/plugins/autopeering/local" - "github.com/iotaledger/goshimmer/packages/gossip" "github.com/iotaledger/goshimmer/packages/model/meta_transaction" "github.com/iotaledger/goshimmer/packages/model/value_transaction" + "github.com/iotaledger/goshimmer/plugins/autopeering/local" "github.com/iotaledger/goshimmer/plugins/tipselection" "github.com/iotaledger/goshimmer/plugins/webapi" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" + "github.com/iotaledger/hive.go/typeutils" + "github.com/iotaledger/iota.go/address" "github.com/iotaledger/iota.go/trinary" "github.com/labstack/echo" ) -var PLUGIN = node.NewPlugin("WebAPI SendData Endpoint", node.Enabled, configure) +var PLUGIN = node.NewPlugin("WebAPI broadcastData Endpoint", node.Enabled, configure) var log *logger.Logger func configure(plugin *node.Plugin) { - log = logger.NewLogger("API-sendData") - webapi.AddEndpoint("sendData", SendDataHandler) + log = logger.NewLogger("API-broadcastData") + webapi.Server.POST("broadcastData", broadcastData) } -func SendDataHandler(c echo.Context) error { - c.Set("requestStartTime", time.Now()) +// broadcastData creates a data (0-value) transaction given an input of bytes and +// broadcasts it to the node's neighbors. It returns the transaction hash if successful. +func broadcastData(c echo.Context) error { var request webRequest if err := c.Bind(&request); err != nil { log.Info(err.Error()) return requestFailed(c, err.Error()) } - log.Info("Received:", request.Data) + log.Debug("Received - address:", request.Address, " data:", request.Data) tx := value_transaction.New() tx.SetHead(true) tx.SetTail(true) - buffer := make([]byte, 6561) - if len(request.Data) > 6561 { - return requestFailed(c, "data exceding 6561 byte limit") + buffer := make([]byte, 2187) + if len(request.Data) > 2187 { + log.Warn("Data exceeding 2187 byte limit -", len(request.Data)) + return requestFailed(c, "Data exceeding 2187 byte limit") } - copy(buffer, []byte(request.Data)) + copy(buffer, typeutils.StringToBytes(request.Data)) trytes, err := trinary.BytesToTrytes(buffer) if err != nil { - log.Info("Trytes conversion", err.Error()) + log.Warn("Trytes conversion failed", err.Error()) + return requestFailed(c, err.Error()) + } + + err = address.ValidAddress(request.Address) + if err != nil { + log.Warn("Invalid Address:", request.Address) return requestFailed(c, err.Error()) } + tx.SetAddress(request.Address) tx.SetSignatureMessageFragment(trytes) + tx.SetValue(0) tx.SetBranchTransactionHash(tipselection.GetRandomTip()) tx.SetTrunkTransactionHash(tipselection.GetRandomTip()) tx.SetTimestamp(uint(time.Now().Unix())) if err := tx.DoProofOfWork(meta_transaction.MIN_WEIGHT_MAGNITUDE); err != nil { log.Warn("PoW failed", err) + return requestFailed(c, err.Error()) } gossip.Events.TransactionReceived.Trigger(&gossip.TransactionReceivedEvent{Data: tx.GetBytes(), Peer: &local.GetInstance().Peer}) @@ -65,25 +77,22 @@ func SendDataHandler(c echo.Context) error { func requestSuccessful(c echo.Context, txHash string) error { return c.JSON(http.StatusCreated, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - TransactionHash: txHash, - Status: "OK", + Hash: txHash, }) } func requestFailed(c echo.Context, message string) error { - return c.JSON(http.StatusNotModified, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - Status: message, + return c.JSON(http.StatusBadRequest, webResponse{ + Error: message, }) } type webResponse struct { - Duration int64 `json:"duration"` - TransactionHash string `json:"transactionHash"` - Status string `json:"status"` + Hash string `json:"hash,omitempty"` + Error string `json:"error,omitempty"` } type webRequest struct { - Data string `json:"data"` + Address string `json:"address"` + Data string `json:"data"` } diff --git a/plugins/webapi/findTransactions/plugin.go b/plugins/webapi/findTransactions/plugin.go new file mode 100644 index 00000000..cf0f1239 --- /dev/null +++ b/plugins/webapi/findTransactions/plugin.go @@ -0,0 +1,67 @@ +package findTransactions + +import ( + "net/http" + + "github.com/iotaledger/goshimmer/plugins/tangle" + "github.com/iotaledger/goshimmer/plugins/webapi" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" + "github.com/iotaledger/iota.go/trinary" + "github.com/labstack/echo" +) + +var PLUGIN = node.NewPlugin("WebAPI findTransactions Endpoint", node.Enabled, configure) +var log *logger.Logger + +func configure(plugin *node.Plugin) { + log = logger.NewLogger("API-findTransactions") + webapi.Server.GET("findTransactions", findTransactions) +} + +// findTransactions returns the array of transaction hashes for the +// given addresses (in the same order as the parameters). +// If a node doesn't have any transaction hash for a given address in its ledger, +// the value at the index of that address is empty. +func findTransactions(c echo.Context) error { + + var request webRequest + + if err := c.Bind(&request); err != nil { + log.Info(err.Error()) + return requestFailed(c, err.Error()) + } + log.Debug("Received:", request.Addresses) + result := make([][]trinary.Trytes, len(request.Addresses)) + + for i, address := range request.Addresses { + txs, err := tangle.ReadTransactionHashesForAddressFromDatabase(address) + if err != nil { + return requestFailed(c, err.Error()) + } + result[i] = append(result[i], txs...) + } + + return requestSuccessful(c, result) +} + +func requestSuccessful(c echo.Context, txHashes [][]trinary.Trytes) error { + return c.JSON(http.StatusOK, webResponse{ + Transactions: txHashes, + }) +} + +func requestFailed(c echo.Context, message string) error { + return c.JSON(http.StatusNotFound, webResponse{ + Error: message, + }) +} + +type webResponse struct { + Transactions [][]trinary.Trytes `json:"transactions,omitempty"` //string + Error string `json:"error,omitempty"` +} + +type webRequest struct { + Addresses []string `json:"addresses"` +} diff --git a/plugins/webapi/getNeighbors/plugin.go b/plugins/webapi/getNeighbors/plugin.go new file mode 100644 index 00000000..01457705 --- /dev/null +++ b/plugins/webapi/getNeighbors/plugin.go @@ -0,0 +1,112 @@ +package getNeighbors + +import ( + "encoding/base64" + "net/http" + + "github.com/iotaledger/goshimmer/packages/autopeering/peer" + "github.com/iotaledger/goshimmer/packages/autopeering/peer/service" + "github.com/iotaledger/goshimmer/plugins/autopeering" + "github.com/iotaledger/goshimmer/plugins/webapi" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" + "github.com/labstack/echo" +) + +var PLUGIN = node.NewPlugin("WebAPI getNeighbors Endpoint", node.Enabled, configure) +var log *logger.Logger + +func configure(plugin *node.Plugin) { + log = logger.NewLogger("API-getNeighbors") + webapi.Server.GET("getNeighbors", getNeighbors) +} + +// getNeighbors returns the chosen and accepted neighbors of the node +func getNeighbors(c echo.Context) error { + + chosen := []neighbor{} + accepted := []neighbor{} + + if autopeering.Selection == nil { + return requestFailed(c, "Neighbor Selection is not enabled") + } + + for _, peer := range autopeering.Selection.GetOutgoingNeighbors() { + + n := neighbor{ + ID: peer.ID().String(), + PublicKey: base64.StdEncoding.EncodeToString(peer.PublicKey()), + } + n.Services = getServices(peer) + chosen = append(chosen, n) + } + for _, peer := range autopeering.Selection.GetIncomingNeighbors() { + n := neighbor{ + ID: peer.ID().String(), + PublicKey: base64.StdEncoding.EncodeToString(peer.PublicKey()), + } + n.Services = getServices(peer) + accepted = append(accepted, n) + } + return requestSuccessful(c, chosen, accepted) + +} + +func requestSuccessful(c echo.Context, chosen, accepted []neighbor) error { + return c.JSON(http.StatusOK, webResponse{ + Chosen: chosen, + Accepted: accepted, + }) +} + +func requestFailed(c echo.Context, message string) error { + return c.JSON(http.StatusNotFound, webResponse{ + Error: message, + }) +} + +type webResponse struct { + Chosen []neighbor `json:"chosen"` + Accepted []neighbor `json:"accepted"` + Error string `json:"error,omitempty"` +} + +type neighbor struct { + ID string `json:"id"` // comparable node identifier + PublicKey string `json:"publicKey"` // public key used to verify signatures + Services []peerService +} + +type peerService struct { + ID string `json:"id"` // ID of the service + Address string `json:"address"` // network address of the service +} + +func getServices(p *peer.Peer) []peerService { + services := []peerService{} + peeringService := p.Services().Get(service.PeeringKey) + if peeringService != nil { + services = append(services, peerService{ + ID: "peering", + Address: peeringService.String(), + }) + } + + gossipService := p.Services().Get(service.GossipKey) + if gossipService != nil { + services = append(services, peerService{ + ID: "gossip", + Address: gossipService.String(), + }) + } + + fpcService := p.Services().Get(service.FPCKey) + if fpcService != nil { + services = append(services, peerService{ + ID: "FPC", + Address: fpcService.String(), + }) + } + + return services +} diff --git a/plugins/webapi/getTransactions/plugin.go b/plugins/webapi/getTransactions/plugin.go new file mode 100644 index 00000000..2dfb696f --- /dev/null +++ b/plugins/webapi/getTransactions/plugin.go @@ -0,0 +1,100 @@ +package getTransactions + +import ( + "net/http" + + "github.com/iotaledger/goshimmer/plugins/tangle" + "github.com/iotaledger/goshimmer/plugins/webapi" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" + "github.com/iotaledger/iota.go/trinary" + "github.com/labstack/echo" +) + +var PLUGIN = node.NewPlugin("WebAPI getTransaction Endpoint", node.Enabled, configure) +var log *logger.Logger + +func configure(plugin *node.Plugin) { + log = logger.NewLogger("API-getTransactions") + webapi.Server.GET("getTransactions", getTransactions) +} + +// getTransactions returns the array of transactions for the +// given transaction hashes (in the same order as the parameters). +// If a node doesn't have the transaction for a given transaction hash in its ledger, +// the value at the index of that transaction hash is empty. +func getTransactions(c echo.Context) error { + + var request webRequest + result := []transaction{} + + if err := c.Bind(&request); err != nil { + log.Info(err.Error()) + return requestFailed(c, err.Error()) + } + log.Debug("Received:", request.Hashes) + + for _, hash := range request.Hashes { + tx, err := tangle.GetTransaction(hash) + if err != nil { + return requestFailed(c, err.Error()) + } + if tx != nil { + t := transaction{ + Hash: tx.GetHash(), + WeightMagnitude: tx.GetWeightMagnitude(), + TrunkTransactionHash: tx.GetTrunkTransactionHash(), + BranchTransactionHash: tx.GetBranchTransactionHash(), + Head: tx.IsHead(), + Tail: tx.IsTail(), + Nonce: tx.GetNonce(), + Address: tx.GetAddress(), + Value: tx.GetValue(), + Timestamp: tx.GetTimestamp(), + SignatureMessageFragment: tx.GetSignatureMessageFragment(), + } + result = append(result, t) + } else { + //tx not found + result = append(result, transaction{}) + } + + } + + return requestSuccessful(c, result) +} + +func requestSuccessful(c echo.Context, txs []transaction) error { + return c.JSON(http.StatusOK, webResponse{ + Transactions: txs, + }) +} + +func requestFailed(c echo.Context, message string) error { + return c.JSON(http.StatusNotFound, webResponse{ + Error: message, + }) +} + +type webResponse struct { + Transactions []transaction `json:"transaction,omitempty"` + Error string `json:"error,omitempty"` +} + +type webRequest struct { + Hashes []string `json:"hashes"` +} + +type transaction struct { + Hash trinary.Trytes `json:"hash,omitempty"` + WeightMagnitude int `json:"weightMagnitude,omitempty"` + TrunkTransactionHash trinary.Trytes `json:"trunkTransactionHash,omitempty"` + BranchTransactionHash trinary.Trytes `json:"branchTransactionHash,omitempty"` + Head bool `json:"head,omitempty"` + Tail bool `json:"tail,omitempty"` + Nonce trinary.Trytes `json:"nonce,omitempty"` + Address trinary.Trytes `json:"address,omitempty"` + Value int64 `json:"value,omitempty"` + Timestamp uint `json:"timestamp,omitempty"` + SignatureMessageFragment trinary.Trytes `json:"signatureMessageFragment,omitempty"` +} diff --git a/plugins/webapi/getTrytes/plugin.go b/plugins/webapi/getTrytes/plugin.go new file mode 100644 index 00000000..4dac6f1b --- /dev/null +++ b/plugins/webapi/getTrytes/plugin.go @@ -0,0 +1,77 @@ +package getTrytes + +import ( + "net/http" + + "github.com/iotaledger/goshimmer/plugins/tangle" + "github.com/iotaledger/goshimmer/plugins/webapi" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" + "github.com/iotaledger/iota.go/trinary" + "github.com/labstack/echo" +) + +var PLUGIN = node.NewPlugin("WebAPI getTrytes Endpoint", node.Enabled, configure) +var log *logger.Logger + +func configure(plugin *node.Plugin) { + log = logger.NewLogger("API-getTrytes") + webapi.Server.GET("getTrytes", getTrytes) +} + +// getTrytes returns the array of transaction trytes for the +// given transaction hashes (in the same order as the parameters). +// If a node doesn't have the trytes for a given transaction hash in its ledger, +// the value at the index of that transaction hash is empty. +func getTrytes(c echo.Context) error { + + var request webRequest + result := []trinary.Trytes{} + if err := c.Bind(&request); err != nil { + log.Info(err.Error()) + return requestFailed(c, err.Error()) + } + log.Debug("Received:", request.Hashes) + + for _, hash := range request.Hashes { + tx, err := tangle.GetTransaction(hash) + if err != nil { + return requestFailed(c, err.Error()) + } + if tx != nil { + trytes, err := trinary.TritsToTrytes(tx.GetTrits()) + // Returns an error if len(tx.GetTrits())%3!=0 + if err != nil { + return requestFailed(c, err.Error()) + } + result = append(result, trytes) + } else { + //tx not found + result = append(result, "") + } + + } + + return requestSuccessful(c, result) +} + +func requestSuccessful(c echo.Context, txTrytes []trinary.Trytes) error { + return c.JSON(http.StatusOK, webResponse{ + Trytes: txTrytes, + }) +} + +func requestFailed(c echo.Context, message string) error { + return c.JSON(http.StatusNotFound, webResponse{ + Error: message, + }) +} + +type webResponse struct { + Trytes []trinary.Trytes `json:"trytes,omitempty"` //string + Error string `json:"error,omitempty"` +} + +type webRequest struct { + Hashes []string `json:"hashes"` +} diff --git a/plugins/webapi-gtta/plugin.go b/plugins/webapi/gtta/plugin.go similarity index 68% rename from plugins/webapi-gtta/plugin.go rename to plugins/webapi/gtta/plugin.go index c873f7a4..3234ddc6 100644 --- a/plugins/webapi-gtta/plugin.go +++ b/plugins/webapi/gtta/plugin.go @@ -1,8 +1,7 @@ -package webapi_gtta +package gtta import ( "net/http" - "time" "github.com/iotaledger/goshimmer/plugins/tipselection" "github.com/iotaledger/goshimmer/plugins/webapi" @@ -11,25 +10,22 @@ import ( "github.com/labstack/echo" ) -var PLUGIN = node.NewPlugin("WebAPI GTTA Endpoint", node.Enabled, func(plugin *node.Plugin) { - webapi.AddEndpoint("getTransactionsToApprove", Handler) +var PLUGIN = node.NewPlugin("WebAPI GTTA Endpoint", node.Disabled, func(plugin *node.Plugin) { + webapi.Server.GET("getTransactionsToApprove", Handler) }) func Handler(c echo.Context) error { - start := time.Now() branchTransactionHash := tipselection.GetRandomTip() trunkTransactionHash := tipselection.GetRandomTip() return c.JSON(http.StatusOK, webResponse{ - Duration: time.Since(start).Nanoseconds() / 1e6, BranchTransaction: branchTransactionHash, TrunkTransaction: trunkTransactionHash, }) } type webResponse struct { - Duration int64 `json:"duration"` BranchTransaction trinary.Trytes `json:"branchTransaction"` TrunkTransaction trinary.Trytes `json:"trunkTransaction"` } diff --git a/plugins/webapi-spammer/plugin.go b/plugins/webapi/spammer/plugin.go similarity index 67% rename from plugins/webapi-spammer/plugin.go rename to plugins/webapi/spammer/plugin.go index fb169eb8..fe29875d 100644 --- a/plugins/webapi-spammer/plugin.go +++ b/plugins/webapi/spammer/plugin.go @@ -1,8 +1,7 @@ -package webapi_spammer +package spammer import ( "net/http" - "time" "github.com/iotaledger/goshimmer/packages/transactionspammer" "github.com/iotaledger/goshimmer/plugins/webapi" @@ -13,11 +12,10 @@ import ( var PLUGIN = node.NewPlugin("Spammer", node.Disabled, configure) func configure(plugin *node.Plugin) { - webapi.AddEndpoint("spammer", WebApiHandler) + webapi.Server.GET("spammer", WebApiHandler) } func WebApiHandler(c echo.Context) error { - c.Set("requestStartTime", time.Now()) var request webRequest if err := c.Bind(&request); err != nil { @@ -27,7 +25,7 @@ func WebApiHandler(c echo.Context) error { switch request.Cmd { case "start": if request.Tps == 0 { - request.Tps = 1000 + request.Tps = 1 } transactionspammer.Stop() @@ -47,24 +45,18 @@ func WebApiHandler(c echo.Context) error { func requestSuccessful(c echo.Context, message string) error { return c.JSON(http.StatusOK, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - Status: "success", - Message: message, + Message: message, }) } func requestFailed(c echo.Context, message string) error { - return c.JSON(http.StatusOK, webResponse{ - Duration: time.Since(c.Get("requestStartTime").(time.Time)).Nanoseconds() / 1e6, - Status: "failed", - Message: message, + return c.JSON(http.StatusNotFound, webResponse{ + Message: message, }) } type webResponse struct { - Duration int64 `json:"duration"` - Status string `json:"status"` - Message string `json:"message"` + Message string `json:"message"` } type webRequest struct { diff --git a/plugins/webauth/webauth.go b/plugins/webauth/webauth.go index b2c898a8..2b904878 100644 --- a/plugins/webauth/webauth.go +++ b/plugins/webauth/webauth.go @@ -41,7 +41,7 @@ func configure(plugin *node.Plugin) { func run(plugin *node.Plugin) { daemon.BackgroundWorker("webauth", func(shutdownSignal <-chan struct{}) { - webapi.AddEndpoint("login", func(c echo.Context) error { + webapi.Server.GET("login", func(c echo.Context) error { username := c.FormValue("username") password := c.FormValue("password") uiUser := os.Getenv("UI_USER") -- GitLab