diff --git a/dapps/valuetransfers/packages/address/signaturescheme/bls.go b/dapps/valuetransfers/packages/address/signaturescheme/bls.go
index 700eb9e4e05d7e4ae3b8f99b5ad2db0acc7f4645..7b10349b0419c144fd89151a071864f7f6bb8e0e 100644
--- a/dapps/valuetransfers/packages/address/signaturescheme/bls.go
+++ b/dapps/valuetransfers/packages/address/signaturescheme/bls.go
@@ -95,7 +95,7 @@ func (sigscheme *blsSignatureScheme) Sign(data []byte) Signature {
 	if err != nil {
 		panic(err)
 	}
-	return newBLSSignature(pubKeyBin, sig)
+	return NewBLSSignature(pubKeyBin, sig)
 }
 
 func (sigscheme *blsSignatureScheme) String() string {
@@ -136,7 +136,8 @@ func BLSSignatureFromBytes(data []byte) (result *BLSSignature, consumedBytes int
 	return
 }
 
-func newBLSSignature(pubKey, signature []byte) *BLSSignature {
+// NewBLSSignature creates BLS signature from raw public key and signature data
+func NewBLSSignature(pubKey, signature []byte) *BLSSignature {
 	var ret BLSSignature
 	ret[0] = address.VersionBLS
 	copy(ret.pubKey(), pubKey)
@@ -223,7 +224,7 @@ func AggregateBLSSignatures(sigs ...Signature) (Signature, error) {
 	if err != nil {
 		return nil, err
 	}
-	return newBLSSignature(pubKeyBin, sigBin), nil
+	return NewBLSSignature(pubKeyBin, sigBin), nil
 }
 
 // interface contract (allow the compiler to check if the implementation has all of the required methods).
diff --git a/dapps/valuetransfers/packages/transaction/outputs.go b/dapps/valuetransfers/packages/transaction/outputs.go
index fd825d65e73b57855c813e5926ccea32b507e1af..4cd77a3ff3962de5e9afb161117f1f420d8da24e 100644
--- a/dapps/valuetransfers/packages/transaction/outputs.go
+++ b/dapps/valuetransfers/packages/transaction/outputs.go
@@ -1,7 +1,9 @@
 package transaction
 
 import (
+	"bytes"
 	"github.com/iotaledger/hive.go/marshalutil"
+	"sort"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
 	"github.com/iotaledger/goshimmer/packages/binary/datastructure/orderedmap"
@@ -16,11 +18,20 @@ type Outputs struct {
 
 // NewOutputs is the constructor of the Outputs struct and creates the list of Outputs from the given details.
 func NewOutputs(outputs map[address.Address][]*balance.Balance) (result *Outputs) {
-	result = &Outputs{orderedmap.New()}
-	for address, balances := range outputs {
-		result.Add(address, balances)
+	// sorting outputs first before adding to the ordered map to have a deterministic order
+	toSort := make([]address.Address, 0, len(outputs))
+	for a := range outputs {
+		toSort = append(toSort, a)
 	}
 
+	sort.Slice(toSort, func(i, j int) bool {
+		return bytes.Compare(toSort[i][:], toSort[j][:]) < 0
+	})
+
+	result = &Outputs{orderedmap.New()}
+	for _, addr := range toSort {
+		result.Add(addr, outputs[addr])
+	}
 	return
 }
 
@@ -49,7 +60,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
 	// iterate the corresponding times and collect addresses + their details
 	for i := uint32(0); i < addressCount; i++ {
 		// read address
-		address, addressErr := address.Parse(marshalUtil)
+		addr, addressErr := address.Parse(marshalUtil)
 		if addressErr != nil {
 			err = addressErr
 
@@ -78,7 +89,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
 		}
 
 		// add the gathered information as an output
-		result.Add(address, coloredBalances)
+		result.Add(addr, coloredBalances)
 	}
 
 	// return the number of bytes we processed
@@ -117,8 +128,8 @@ func (outputs *Outputs) Bytes() []byte {
 		marshalUtil.WriteBytes(address.Bytes())
 		marshalUtil.WriteUint32(uint32(len(balances)))
 
-		for _, balance := range balances {
-			marshalUtil.WriteBytes(balance.Bytes())
+		for _, bal := range balances {
+			marshalUtil.WriteBytes(bal.Bytes())
 		}
 
 		return true
@@ -141,10 +152,10 @@ func (outputs *Outputs) String() string {
 		result += "    " + address.String() + ": [\n"
 
 		balancesEmpty := true
-		for _, balance := range balances {
+		for _, bal := range balances {
 			balancesEmpty = false
 
-			result += "        " + balance.String() + ",\n"
+			result += "        " + bal.String() + ",\n"
 		}
 
 		if balancesEmpty {
diff --git a/dapps/valuetransfers/packages/transaction/outputs_test.go b/dapps/valuetransfers/packages/transaction/outputs_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..4c76e4cc44032b9078e95138af2c10dbc15d86c5
--- /dev/null
+++ b/dapps/valuetransfers/packages/transaction/outputs_test.go
@@ -0,0 +1,45 @@
+package transaction
+
+import (
+	"bytes"
+
+	"github.com/stretchr/testify/assert"
+
+	"testing"
+
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
+	"golang.org/x/crypto/blake2b"
+)
+
+func TestOutputs(t *testing.T) {
+	rndAddrs := make([]address.Address, 15)
+	for i := range rndAddrs {
+		rndAddrs[i] = address.RandomOfType(address.VersionED25519)
+	}
+
+	theMap1 := make(map[address.Address][]*balance.Balance)
+	for i := 0; i < len(rndAddrs); i++ {
+		theMap1[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
+	}
+	out1 := NewOutputs(theMap1)
+
+	theMap2 := make(map[address.Address][]*balance.Balance)
+	for i := len(rndAddrs) - 1; i >= 0; i-- {
+		theMap2[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
+	}
+	out2 := NewOutputs(theMap2)
+
+	h1 := hashOutputs(t, out1)
+	h2 := hashOutputs(t, out2)
+
+	assert.Equal(t, bytes.Equal(h1, h2), true)
+}
+
+func hashOutputs(t *testing.T, out *Outputs) []byte {
+	h, err := blake2b.New256(nil)
+	assert.NoError(t, err)
+
+	h.Write(out.Bytes())
+	return h.Sum(nil)
+}
diff --git a/dapps/valuetransfers/packages/transaction/transaction.go b/dapps/valuetransfers/packages/transaction/transaction.go
index 0bbe730cc1b4e83a74c3e2a5f414fa4d85448b30..cf73c9f66443661639e9902c0363b5f664670268 100644
--- a/dapps/valuetransfers/packages/transaction/transaction.go
+++ b/dapps/valuetransfers/packages/transaction/transaction.go
@@ -1,6 +1,7 @@
 package transaction
 
 import (
+	"errors"
 	"fmt"
 	"sync"
 
@@ -277,6 +278,16 @@ func (transaction *Transaction) Sign(signature signaturescheme.SignatureScheme)
 	return transaction
 }
 
+// PutSignature validates and adds signature to the transaction
+func (transaction *Transaction) PutSignature(signature signaturescheme.Signature) error {
+	if !signature.IsValid(transaction.EssenceBytes()) {
+		return errors.New("PutSignature: invalid signature")
+	}
+	transaction.signatures.Add(signature.Address(), signature)
+
+	return nil
+}
+
 // String returns a human readable version of this Transaction (for debug purposes).
 func (transaction *Transaction) String() string {
 	id := transaction.ID()
diff --git a/dapps/valuetransfers/packages/transaction/transaction_test.go b/dapps/valuetransfers/packages/transaction/transaction_test.go
index 757a0060ac92821ab1a87b125018f56d55d30ac8..38bee17bdb987c61c0159fbcfd8cda50b9cdf20a 100644
--- a/dapps/valuetransfers/packages/transaction/transaction_test.go
+++ b/dapps/valuetransfers/packages/transaction/transaction_test.go
@@ -38,7 +38,7 @@ func TestShortDataPayload(t *testing.T) {
 
 	dataPayload := []byte("data payload test")
 	err := tx.SetDataPayload(dataPayload)
-	assert.Equal(t, nil, err)
+	assert.NoError(t, err)
 
 	dpBack := tx.GetDataPayload()
 	assert.Equal(t, true, bytes.Equal(dpBack, dataPayload))
@@ -52,7 +52,7 @@ func TestShortDataPayload(t *testing.T) {
 	tx.essenceBytes = nil
 	dataPayload[2] = '?'
 	err = tx.SetDataPayload(dataPayload)
-	assert.Equal(t, nil, err)
+	assert.NoError(t, err)
 
 	// expect signature is not valid
 	check = tx.SignaturesValid()
@@ -70,7 +70,7 @@ func TestTooLongDataPayload(t *testing.T) {
 
 	dataPayload := []byte(strings.Repeat("1", MaxDataPayloadSize+1))
 	err := tx.SetDataPayload(dataPayload)
-	assert.Equal(t, true, err != nil)
+	assert.Error(t, err)
 }
 
 func TestMarshalingEmptyDataPayload(t *testing.T) {
@@ -90,9 +90,8 @@ func TestMarshalingEmptyDataPayload(t *testing.T) {
 
 	tx1 := Transaction{}
 	_, err := tx1.UnmarshalObjectStorageValue(v)
-	if err != nil {
-		assert.Error(t, err)
-	}
+	assert.NoError(t, err)
+
 	assert.Equal(t, true, tx1.SignaturesValid())
 	assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
 }
@@ -108,7 +107,7 @@ func TestMarshalingDataPayload(t *testing.T) {
 
 	dataPayload := []byte("data payload test")
 	err := tx.SetDataPayload(dataPayload)
-	assert.Equal(t, nil, err)
+	assert.NoError(t, err)
 
 	tx.Sign(sigScheme)
 	check := tx.SignaturesValid()
@@ -119,8 +118,73 @@ func TestMarshalingDataPayload(t *testing.T) {
 	tx1 := Transaction{}
 	_, err = tx1.UnmarshalObjectStorageValue(v)
 
-	assert.Equal(t, nil, err)
+	assert.NoError(t, err)
 	assert.Equal(t, true, tx1.SignaturesValid())
 
 	assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
 }
+
+func TestPutSignatureValid(t *testing.T) {
+	sigScheme := signaturescheme.RandBLS()
+	addr := sigScheme.Address()
+	o1 := NewOutputID(addr, RandomID())
+	inputs := NewInputs(o1)
+	bal := balance.New(balance.ColorIOTA, 1)
+	outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
+	tx := New(inputs, outputs)
+
+	dataPayload := []byte("data payload test")
+	err := tx.SetDataPayload(dataPayload)
+	assert.NoError(t, err)
+
+	signature := sigScheme.Sign(tx.EssenceBytes())
+	assert.Equal(t, signature.IsValid(tx.EssenceBytes()), true)
+
+	err = tx.PutSignature(signature)
+	assert.NoError(t, err)
+
+	check := tx.SignaturesValid()
+	assert.Equal(t, true, check)
+}
+
+func TestPutSignatureInvalid(t *testing.T) {
+	sigScheme := signaturescheme.RandBLS()
+	addr := sigScheme.Address()
+	o1 := NewOutputID(addr, RandomID())
+	inputs := NewInputs(o1)
+	bal := balance.New(balance.ColorIOTA, 1)
+	outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
+	tx := New(inputs, outputs)
+
+	dataPayload := []byte("data payload test")
+	err := tx.SetDataPayload(dataPayload)
+	assert.NoError(t, err)
+
+	signatureValid := sigScheme.Sign(tx.EssenceBytes())
+	assert.Equal(t, true, signatureValid.IsValid(tx.EssenceBytes()))
+
+	sigBytes := make([]byte, len(signatureValid.Bytes()))
+	copy(sigBytes, signatureValid.Bytes())
+	// inverse last byte --> corrupt the signatureValid
+	sigBytes[len(sigBytes)-1] = ^sigBytes[len(sigBytes)-1]
+
+	sigCorrupted, consumed, err := signaturescheme.BLSSignatureFromBytes(sigBytes)
+
+	assert.NoError(t, err)
+	assert.Equal(t, consumed, len(sigBytes))
+	assert.Equal(t, false, sigCorrupted.IsValid(tx.EssenceBytes()))
+
+	err = tx.PutSignature(sigCorrupted)
+	// error expected
+	assert.Error(t, err)
+
+	// 0 signatures is not valid
+	assert.Equal(t, true, !tx.SignaturesValid())
+
+	err = tx.PutSignature(signatureValid)
+	// no error expected
+	assert.NoError(t, err)
+
+	// valid signatures expected
+	assert.Equal(t, true, tx.SignaturesValid())
+}