Skip to content
Snippets Groups Projects
Commit 7020446b authored by capossele's avatar capossele
Browse files

Merge branch 'develop' into fix/dashboard-drng

parents bc791bd8 b8c48b20
No related branches found
No related tags found
No related merge requests found
...@@ -34,6 +34,12 @@ func Random() (address Address) { ...@@ -34,6 +34,12 @@ func Random() (address Address) {
return return
} }
func RandomOfType(versionByte byte) Address {
ret := Random()
ret[0] = versionByte
return ret
}
// FromBase58 creates an address from a base58 encoded string. // FromBase58 creates an address from a base58 encoded string.
func FromBase58(base58String string) (address Address, err error) { func FromBase58(base58String string) (address Address, err error) {
// decode string // decode string
......
...@@ -14,7 +14,7 @@ import ( ...@@ -14,7 +14,7 @@ import (
"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address/signaturescheme" "github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address/signaturescheme"
) )
// region IMPLEMENT Transaction /////////////////////////////////////////////////////////////////////////////////////////// // region IMPLEMENT Transaction ////////////////////////////////////////////////////////////////////////////////////////////
type Transaction struct { type Transaction struct {
objectstorage.StorableObjectFlags objectstorage.StorableObjectFlags
...@@ -32,6 +32,9 @@ type Transaction struct { ...@@ -32,6 +32,9 @@ type Transaction struct {
signatureBytes []byte signatureBytes []byte
signatureBytesMutex sync.RWMutex signatureBytesMutex sync.RWMutex
dataPayload []byte
dataPayloadMutex sync.RWMutex
bytes []byte bytes []byte
bytesMutex sync.RWMutex bytesMutex sync.RWMutex
} }
...@@ -182,6 +185,12 @@ func (transaction *Transaction) EssenceBytes() []byte { ...@@ -182,6 +185,12 @@ func (transaction *Transaction) EssenceBytes() []byte {
// marshal outputs // marshal outputs
marshalUtil.WriteBytes(transaction.outputs.Bytes()) marshalUtil.WriteBytes(transaction.outputs.Bytes())
// marshal dataPayload size
marshalUtil.WriteUint32(transaction.DataPayloadSize())
// marshal dataPayload data
marshalUtil.WriteBytes(transaction.dataPayload)
// store marshaled result // store marshaled result
transaction.essenceBytes = marshalUtil.Bytes() transaction.essenceBytes = marshalUtil.Bytes()
...@@ -260,9 +269,42 @@ func (transaction *Transaction) String() string { ...@@ -260,9 +269,42 @@ func (transaction *Transaction) String() string {
stringify.StructField("inputs", transaction.inputs), stringify.StructField("inputs", transaction.inputs),
stringify.StructField("outputs", transaction.outputs), stringify.StructField("outputs", transaction.outputs),
stringify.StructField("signatures", transaction.signatures), stringify.StructField("signatures", transaction.signatures),
stringify.StructField("dataPayloadSize", transaction.DataPayloadSize()),
) )
} }
// max dataPayload size limit
const MAX_DATA_PAYLOAD_SIZE = 64 * 1024
// SetDataPayload sets yhe dataPayload and its type
func (transaction *Transaction) SetDataPayload(data []byte) error {
transaction.dataPayloadMutex.Lock()
defer transaction.dataPayloadMutex.Unlock()
if len(data) > MAX_DATA_PAYLOAD_SIZE {
return fmt.Errorf("maximum dataPayload size of %d bytes exceeded", MAX_DATA_PAYLOAD_SIZE)
}
transaction.dataPayload = data
return nil
}
// GetDataPayload gets the dataPayload and its type
func (transaction *Transaction) GetDataPayload() []byte {
transaction.dataPayloadMutex.RLock()
defer transaction.dataPayloadMutex.RUnlock()
return transaction.dataPayload
}
// DataPayloadSize returns the size of the dataPayload as uint32.
// nil payload as size 0
func (transaction *Transaction) DataPayloadSize() uint32 {
transaction.dataPayloadMutex.RLock()
defer transaction.dataPayloadMutex.RUnlock()
return uint32(len(transaction.dataPayload))
}
// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
// region IMPLEMENT StorableObject interface /////////////////////////////////////////////////////////////////////////// // region IMPLEMENT StorableObject interface ///////////////////////////////////////////////////////////////////////////
...@@ -301,6 +343,24 @@ func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (err e ...@@ -301,6 +343,24 @@ func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (err e
} }
transaction.outputs = parsedOutputs.(*Outputs) transaction.outputs = parsedOutputs.(*Outputs)
// unmarshal data payload size
var dataPayloadSize uint32
dataPayloadSize, err = marshalUtil.ReadUint32()
if err != nil {
return
}
if dataPayloadSize > MAX_DATA_PAYLOAD_SIZE {
err = fmt.Errorf("data payload size of %d bytes exceeds maximum limit of %d bytes",
dataPayloadSize, MAX_DATA_PAYLOAD_SIZE)
return
}
// unmarshal data payload
transaction.dataPayload, err = marshalUtil.ReadBytes(int(dataPayloadSize))
if err != nil {
return
}
// store essence bytes // store essence bytes
essenceBytesCount := marshalUtil.ReadOffset() essenceBytesCount := marshalUtil.ReadOffset()
transaction.essenceBytes = make([]byte, essenceBytesCount) transaction.essenceBytes = make([]byte, essenceBytesCount)
......
package transaction
import (
"bytes"
"strings"
"testing"
"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address"
"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address/signaturescheme"
"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/balance"
"github.com/iotaledger/hive.go/crypto/ed25519"
"github.com/stretchr/testify/assert"
)
func TestEmptyDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputId(addr, RandomId())
inputs := NewInputs(o1)
bal := balance.New(balance.COLOR_IOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
}
func TestShortDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputId(addr, RandomId())
inputs := NewInputs(o1)
bal := balance.New(balance.COLOR_IOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err)
dpBack := tx.GetDataPayload()
assert.Equal(t, true, bytes.Equal(dpBack, dataPayload))
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
// corrupt data payload bytes
// reset essence to force recalculation
tx.essenceBytes = nil
dataPayload[2] = '?'
err = tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err)
// expect signature is not valid
check = tx.SignaturesValid()
assert.Equal(t, false, check)
}
func TestTooLongDataPayload(t *testing.T) {
sigScheme := signaturescheme.ED25519(ed25519.GenerateKeyPair())
addr := sigScheme.Address()
o1 := NewOutputId(addr, RandomId())
inputs := NewInputs(o1)
bal := balance.New(balance.COLOR_IOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte(strings.Repeat("1", MAX_DATA_PAYLOAD_SIZE+1))
err := tx.SetDataPayload(dataPayload)
assert.Equal(t, true, err != nil)
}
func TestMarshalingEmptyDataPayload(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputId(addr, RandomId())
inputs := NewInputs(o1)
bal := balance.New(balance.COLOR_IOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
v := tx.ObjectStorageValue()
tx1 := Transaction{}
err, _ := tx1.UnmarshalObjectStorageValue(v)
if err != nil {
assert.Error(t, err)
}
assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.Id().Bytes(), tx.Id().Bytes()))
}
func TestMarshalingDataPayload(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputId(addr, RandomId())
inputs := NewInputs(o1)
bal := balance.New(balance.COLOR_IOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err)
tx.Sign(sigScheme)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
v := tx.ObjectStorageValue()
tx1 := Transaction{}
err, _ = tx1.UnmarshalObjectStorageValue(v)
assert.Equal(t, nil, err)
assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.Id().Bytes(), tx.Id().Bytes()))
}
...@@ -387,7 +387,7 @@ func TestDropNeighbor(t *testing.T) { ...@@ -387,7 +387,7 @@ func TestDropNeighbor(t *testing.T) {
go func() { assert.NoError(t, mgrA.AddInbound(peerB)) }() go func() { assert.NoError(t, mgrA.AddInbound(peerB)) }()
go func() { assert.NoError(t, mgrB.AddOutbound(peerA)) }() go func() { assert.NoError(t, mgrB.AddOutbound(peerA)) }()
wg.Wait() // wait until the events were triggered wg.Wait() // wait until the events were triggered and the peers are connected
} }
disc := func() { disc := func() {
var wg sync.WaitGroup var wg sync.WaitGroup
...@@ -396,9 +396,17 @@ func TestDropNeighbor(t *testing.T) { ...@@ -396,9 +396,17 @@ func TestDropNeighbor(t *testing.T) {
Events.NeighborRemoved.Attach(closure) Events.NeighborRemoved.Attach(closure)
defer Events.NeighborRemoved.Detach(closure) defer Events.NeighborRemoved.Detach(closure)
go func() { _ = mgrA.DropNeighbor(peerB.ID()) }() // assure that no DropNeighbor calls are leaking
go func() { _ = mgrB.DropNeighbor(peerA.ID()) }() wg.Add(2)
wg.Wait() // wait until the events were triggered go func() {
defer wg.Done()
_ = mgrA.DropNeighbor(peerB.ID())
}()
go func() {
defer wg.Done()
_ = mgrB.DropNeighbor(peerA.ID())
}()
wg.Wait() // wait until the events were triggered and the go routines are done
} }
// drop and connect many many times // drop and connect many many times
......
...@@ -5,13 +5,16 @@ import ( ...@@ -5,13 +5,16 @@ import (
) )
const ( const (
WEBAPI_AUTH_USERNAME = "webapi.auth.username" // CfgWebAPIAuthUsername defines the config flag of the web API authentication username.
WEBAPI_AUTH_PASSWORD = "webapi.auth.password" CfgWebAPIAuthUsername = "webapi.auth.username"
WEBAPI_AUTH_PRIVATE_KEY = "webapi.auth.privateKey" // CfgWebAPIAuthPassword defines the config flag of the web API authentication password.
CfgWebAPIAuthPassword = "webapi.auth.password"
// CfgWebAPIAuthPrivateKey defines the config flag of the web API authentication private key.
CfgWebAPIAuthPrivateKey = "webapi.auth.privateKey"
) )
func init() { func init() {
flag.String(WEBAPI_AUTH_USERNAME, "goshimmer", "username for the webapi") flag.String(CfgWebAPIAuthUsername, "goshimmer", "username for the webapi")
flag.String(WEBAPI_AUTH_PASSWORD, "goshimmer", "password for the webapi") flag.String(CfgWebAPIAuthPassword, "goshimmer", "password for the webapi")
flag.String(WEBAPI_AUTH_PRIVATE_KEY, "", "private key used to sign the JWTs") flag.String(CfgWebAPIAuthPrivateKey, "", "private key used to sign the JWTs")
} }
...@@ -5,15 +5,13 @@ import ( ...@@ -5,15 +5,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/dgrijalva/jwt-go"
"github.com/iotaledger/goshimmer/plugins/config"
"github.com/iotaledger/goshimmer/plugins/webapi"
"github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/logger"
"github.com/iotaledger/hive.go/node" "github.com/iotaledger/hive.go/node"
"github.com/labstack/echo" "github.com/labstack/echo"
"github.com/labstack/echo/middleware" "github.com/labstack/echo/middleware"
"github.com/iotaledger/goshimmer/plugins/config"
"github.com/iotaledger/goshimmer/plugins/webapi"
"github.com/dgrijalva/jwt-go"
) )
// PluginName is the name of the web API auth plugin. // PluginName is the name of the web API auth plugin.
...@@ -28,7 +26,7 @@ var ( ...@@ -28,7 +26,7 @@ var (
func configure(plugin *node.Plugin) { func configure(plugin *node.Plugin) {
log = logger.NewLogger(PluginName) log = logger.NewLogger(PluginName)
privateKey = config.Node.GetString(WEBAPI_AUTH_PRIVATE_KEY) privateKey = config.Node.GetString(CfgWebAPIAuthPrivateKey)
if len(privateKey) == 0 { if len(privateKey) == 0 {
panic("") panic("")
} }
...@@ -47,23 +45,29 @@ func configure(plugin *node.Plugin) { ...@@ -47,23 +45,29 @@ func configure(plugin *node.Plugin) {
log.Info("WebAPI is now secured through JWT authentication") log.Info("WebAPI is now secured through JWT authentication")
} }
// Request defines the struct of the request.
type Request struct { type Request struct {
// Username is the username of the request.
Username string `json:"username"` Username string `json:"username"`
// Password is the password of the request.
Password string `json:"password"` Password string `json:"password"`
} }
// Response defines the struct of the response.
type Response struct { type Response struct {
// Token is the json web token.
Token string `json:"token"` Token string `json:"token"`
} }
// Handler handles the web auth request.
func Handler(c echo.Context) error { func Handler(c echo.Context) error {
login := &Request{} login := &Request{}
if err := c.Bind(login); err != nil { if err := c.Bind(login); err != nil {
return echo.ErrBadRequest return echo.ErrBadRequest
} }
if login.Username != config.Node.GetString(WEBAPI_AUTH_USERNAME) || if login.Username != config.Node.GetString(CfgWebAPIAuthUsername) ||
login.Password != config.Node.GetString(WEBAPI_AUTH_PASSWORD) { login.Password != config.Node.GetString(CfgWebAPIAuthPassword) {
return echo.ErrUnauthorized return echo.ErrUnauthorized
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment