Skip to content
Snippets Groups Projects
Unverified Commit b33aa943 authored by lunfardo314's avatar lunfardo314 Committed by GitHub
Browse files

Merge pull request #332 from lunfardo314/develop

data payload of the value transaction
parents 537649c7 1cc62930
No related branches found
No related tags found
No related merge requests found
......@@ -34,6 +34,12 @@ func Random() (address Address) {
return
}
func RandomOfType(versionByte byte) Address {
ret := Random()
ret[0] = versionByte
return ret
}
// FromBase58 creates an address from a base58 encoded string.
func FromBase58(base58String string) (address Address, err error) {
// decode string
......
......@@ -14,7 +14,7 @@ import (
"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address/signaturescheme"
)
// region IMPLEMENT Transaction ///////////////////////////////////////////////////////////////////////////////////////////
// region IMPLEMENT Transaction ////////////////////////////////////////////////////////////////////////////////////////////
type Transaction struct {
objectstorage.StorableObjectFlags
......@@ -32,6 +32,9 @@ type Transaction struct {
signatureBytes []byte
signatureBytesMutex sync.RWMutex
dataPayload []byte
dataPayloadMutex sync.RWMutex
bytes []byte
bytesMutex sync.RWMutex
}
......@@ -182,6 +185,12 @@ func (transaction *Transaction) EssenceBytes() []byte {
// marshal outputs
marshalUtil.WriteBytes(transaction.outputs.Bytes())
// marshal dataPayload size
marshalUtil.WriteUint32(transaction.DataPayloadSize())
// marshal dataPayload data
marshalUtil.WriteBytes(transaction.dataPayload)
// store marshaled result
transaction.essenceBytes = marshalUtil.Bytes()
......@@ -260,9 +269,42 @@ func (transaction *Transaction) String() string {
stringify.StructField("inputs", transaction.inputs),
stringify.StructField("outputs", transaction.outputs),
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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
// region IMPLEMENT StorableObject interface ///////////////////////////////////////////////////////////////////////////
......@@ -301,6 +343,24 @@ func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (err e
}
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
essenceBytesCount := marshalUtil.ReadOffset()
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()))
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment