Skip to content
Snippets Groups Projects
  • Angelo Capossele's avatar
    ed435f7d
    Adds a HTTP API to query and create transactions (#95) · ed435f7d
    Angelo Capossele authored
    * :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
    ed435f7d
    History
    Adds a HTTP API to query and create transactions (#95)
    Angelo Capossele authored
    * :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
plugin.go 2.90 KiB
package broadcastData

import (
	"net/http"
	"time"

	"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 broadcastData Endpoint", node.Enabled, configure)
var log *logger.Logger

func configure(plugin *node.Plugin) {
	log = logger.NewLogger("API-broadcastData")
	webapi.Server.POST("broadcastData", broadcastData)
}

// 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.Debug("Received - address:", request.Address, " data:", request.Data)
	tx := value_transaction.New()
	tx.SetHead(true)
	tx.SetTail(true)

	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, typeutils.StringToBytes(request.Data))

	trytes, err := trinary.BytesToTrytes(buffer)
	if err != nil {
		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})
	return requestSuccessful(c, tx.GetHash())
}

func requestSuccessful(c echo.Context, txHash string) error {
	return c.JSON(http.StatusCreated, webResponse{
		Hash: txHash,
	})
}

func requestFailed(c echo.Context, message string) error {
	return c.JSON(http.StatusBadRequest, webResponse{
		Error: message,
	})
}

type webResponse struct {
	Hash  string `json:"hash,omitempty"`
	Error string `json:"error,omitempty"`
}

type webRequest struct {
	Address string `json:"address"`
	Data    string `json:"data"`
}