diff --git a/packages/binary/datastructure/orderedmap/orderedmap.go b/packages/binary/datastructure/orderedmap/orderedmap.go
index d92c1e8c3b67f1292d87e2e50f4d09d86c984f92..fe0555421f1a5146b3f63e863c93d68192a033e5 100644
--- a/packages/binary/datastructure/orderedmap/orderedmap.go
+++ b/packages/binary/datastructure/orderedmap/orderedmap.go
@@ -67,14 +67,18 @@ func (orderedMap *OrderedMap) Set(key interface{}, newValue interface{}) bool {
 }
 
 func (orderedMap *OrderedMap) ForEach(consumer func(key, value interface{}) bool) {
+	orderedMap.mutex.RLock()
 	currentEntry := orderedMap.head
+	orderedMap.mutex.RUnlock()
 
 	for currentEntry != nil {
 		if !consumer(currentEntry.key, currentEntry.value) {
 			return
 		}
 
+		orderedMap.mutex.RLock()
 		currentEntry = currentEntry.next
+		orderedMap.mutex.RUnlock()
 	}
 }
 
diff --git a/packages/binary/marshalutil/marshalutil.byte.go b/packages/binary/marshalutil/marshalutil.byte.go
new file mode 100644
index 0000000000000000000000000000000000000000..37e15bf71d31107e46f59e2e0c52fed7566d14e5
--- /dev/null
+++ b/packages/binary/marshalutil/marshalutil.byte.go
@@ -0,0 +1,20 @@
+package marshalutil
+
+func (util *MarshalUtil) WriteByte(byte byte) {
+	writeEndOffset := util.expandWriteCapacity(1)
+
+	util.bytes[util.writeOffset] = byte
+
+	util.WriteSeek(writeEndOffset)
+}
+
+func (util *MarshalUtil) ReadByte() (byte, error) {
+	readEndOffset, err := util.checkReadCapacity(1)
+	if err != nil {
+		return 0, err
+	}
+
+	defer util.ReadSeek(readEndOffset)
+
+	return util.bytes[util.readOffset], nil
+}
diff --git a/packages/binary/marshalutil/marshalutil.bytes.go b/packages/binary/marshalutil/marshalutil.bytes.go
index 5f2c298fce9440247db38a98e8d1326b8e56a921..22d2580acf9eb3185368cd33d893e1f0d690ade6 100644
--- a/packages/binary/marshalutil/marshalutil.bytes.go
+++ b/packages/binary/marshalutil/marshalutil.bytes.go
@@ -9,6 +9,10 @@ func (util *MarshalUtil) WriteBytes(bytes []byte) {
 }
 
 func (util *MarshalUtil) ReadBytes(length int) ([]byte, error) {
+	if length < 0 {
+		length = len(util.bytes) - util.readOffset + length
+	}
+
 	readEndOffset, err := util.checkReadCapacity(length)
 	if err != nil {
 		return nil, err
diff --git a/packages/binary/marshalutil/marshalutil.go b/packages/binary/marshalutil/marshalutil.go
index 733ee12f038b32b54413e2071b676375d1dbd064..f6e95e704af690b4f7cdc22fc0ec5a442e1ee722 100644
--- a/packages/binary/marshalutil/marshalutil.go
+++ b/packages/binary/marshalutil/marshalutil.go
@@ -56,11 +56,19 @@ func (util *MarshalUtil) WriteOffset() int {
 }
 
 func (util *MarshalUtil) WriteSeek(offset int) {
-	util.writeOffset = offset
+	if offset < 0 {
+		util.writeOffset += offset
+	} else {
+		util.writeOffset = offset
+	}
 }
 
 func (util *MarshalUtil) ReadSeek(offset int) {
-	util.readOffset = offset
+	if offset < 0 {
+		util.readOffset += offset
+	} else {
+		util.readOffset = offset
+	}
 }
 
 func (util *MarshalUtil) Bytes() []byte {
diff --git a/packages/binary/signature/ed25119/public_key.go b/packages/binary/signature/ed25119/public_key.go
index c9d58e254413349234283406c817f8c68c7d30e5..9afe9766d147c05f17b1ce6f4c7f256fc18bbb05 100644
--- a/packages/binary/signature/ed25119/public_key.go
+++ b/packages/binary/signature/ed25119/public_key.go
@@ -2,12 +2,27 @@ package ed25119
 
 import (
 	"errors"
+	"fmt"
 
 	"github.com/oasislabs/ed25519"
 )
 
 type PublicKey [PublicKeySize]byte
 
+func PublicKeyFromBytes(bytes []byte) (result PublicKey, err error, consumedBytes int) {
+	if len(bytes) < PublicKeySize {
+		err = fmt.Errorf("bytes too short")
+
+		return
+	}
+
+	copy(result[:], bytes)
+
+	consumedBytes = PublicKeySize
+
+	return
+}
+
 func (publicKey PublicKey) VerifySignature(data []byte, signature Signature) bool {
 	return ed25519.Verify(publicKey[:], data, signature[:])
 }
diff --git a/packages/binary/signature/ed25119/signature.go b/packages/binary/signature/ed25119/signature.go
index bd33e1138e42da2809b0dac22afa1a140d5b8c3b..d8a291eec642f9714b15160dd27ea3f8b40c5b0d 100644
--- a/packages/binary/signature/ed25119/signature.go
+++ b/packages/binary/signature/ed25119/signature.go
@@ -2,10 +2,25 @@ package ed25119
 
 import (
 	"errors"
+	"fmt"
 )
 
 type Signature [SignatureSize]byte
 
+func SignatureFromBytes(bytes []byte) (result Signature, err error, consumedBytes int) {
+	if len(bytes) < SignatureSize {
+		err = fmt.Errorf("bytes too short")
+
+		return
+	}
+
+	copy(result[:SignatureSize], bytes)
+
+	consumedBytes = SignatureSize
+
+	return
+}
+
 func (signature *Signature) UnmarshalBinary(bytes []byte) (err error) {
 	if len(bytes) < SignatureSize {
 		return errors.New("not enough bytes")
diff --git a/packages/binary/tangle/model/transaction/id.go b/packages/binary/tangle/model/transaction/id.go
index dd5ca1544b311f85740893dd416a04358cb74267..03c17fa2b4a9a03ed11dbb23d6a203a479f40f96 100644
--- a/packages/binary/tangle/model/transaction/id.go
+++ b/packages/binary/tangle/model/transaction/id.go
@@ -1,30 +1,60 @@
 package transaction
 
 import (
+	"fmt"
+
 	"github.com/mr-tron/base58"
 )
 
 type Id [IdLength]byte
 
-func NewId(id []byte) (result Id) {
-	copy(result[:], id)
+func NewId(base58EncodedString string) (result Id, err error) {
+	bytes, err := base58.Decode(base58EncodedString)
+	if err != nil {
+		return
+	}
+
+	if len(bytes) != IdLength {
+		err = fmt.Errorf("length of base58 formatted transaction id is wrong")
+
+		return
+	}
+
+	copy(result[:], bytes)
 
 	return
 }
 
-func (id *Id) MarshalBinary() (result []byte, err error) {
-	result = make([]byte, IdLength)
-	copy(result, id[:])
+// IdFromBytes unmarshals a transaction id from a sequence of bytes.
+func IdFromBytes(bytes []byte) (result Id, err error, consumedBytes int) {
+	// check arguments
+	if len(bytes) < IdLength {
+		err = fmt.Errorf("bytes not long enough to encode a valid transaction id")
+	}
+
+	// calculate result
+	copy(result[:], bytes)
+
+	// return the number of bytes we processed
+	consumedBytes = IdLength
 
 	return
 }
 
+func (id *Id) MarshalBinary() (result []byte, err error) {
+	return id.Bytes(), nil
+}
+
 func (id *Id) UnmarshalBinary(data []byte) (err error) {
 	copy(id[:], data)
 
 	return
 }
 
+func (id Id) Bytes() []byte {
+	return id[:]
+}
+
 func (id Id) String() string {
 	return base58.Encode(id[:])
 }
diff --git a/packages/binary/tangle/model/transaction/payload/data/data.go b/packages/binary/tangle/model/transaction/payload/data/data.go
index 8b41b99ce062ee65fee8cbd25b5561bc50b7a538..84bc43b7da9be36c6479f5381dbab6bec64ffc79 100644
--- a/packages/binary/tangle/model/transaction/payload/data/data.go
+++ b/packages/binary/tangle/model/transaction/payload/data/data.go
@@ -1,6 +1,9 @@
 package data
 
 import (
+	"github.com/iotaledger/hive.go/stringify"
+
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload"
 )
 
@@ -18,6 +21,29 @@ func New(data []byte) *Data {
 	}
 }
 
+func FromBytes(bytes []byte, optionalTargetObject ...*Data) (result *Data, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &Data{}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to FromBytes")
+	}
+
+	// initialize helper
+	marshalUtil := marshalutil.New(bytes)
+
+	// read data
+	result.data = marshalUtil.ReadRemainingBytes()
+
+	// return the number of bytes we processed
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
 func (dataPayload *Data) GetType() payload.Type {
 	return dataPayload.payloadType
 }
@@ -26,20 +52,34 @@ func (dataPayload *Data) GetData() []byte {
 	return dataPayload.data
 }
 
-func (dataPayload *Data) UnmarshalBinary(data []byte) error {
-	dataPayload.data = make([]byte, len(data))
-	copy(dataPayload.data, data)
+// Bytes marshals the data payload into a sequence of bytes.
+func (dataPayload *Data) Bytes() []byte {
+	// initialize helper
+	marshalUtil := marshalutil.New()
+
+	// write the data as raw bytes
+	marshalUtil.WriteBytes(dataPayload.data[:])
 
-	return nil
+	// return result
+	return marshalUtil.Bytes()
 }
 
-func (dataPayload *Data) MarshalBinary() (data []byte, err error) {
-	data = make([]byte, len(dataPayload.data))
-	copy(data, dataPayload.data)
+func (dataPayload *Data) UnmarshalBinary(data []byte) (err error) {
+	_, err, _ = FromBytes(data, dataPayload)
 
 	return
 }
 
+func (dataPayload *Data) MarshalBinary() (data []byte, err error) {
+	return dataPayload.Bytes(), nil
+}
+
+func (dataPayload *Data) String() string {
+	return stringify.Struct("Data",
+		stringify.StructField("data", string(dataPayload.GetData())),
+	)
+}
+
 func GenericPayloadUnmarshalerFactory(payloadType payload.Type) payload.Unmarshaler {
 	return func(data []byte) (payload payload.Payload, err error) {
 		payload = &Data{
diff --git a/packages/binary/tangle/model/transaction/payload/payload.go b/packages/binary/tangle/model/transaction/payload/payload.go
index 23ff09be788c7dc242b3fd640813e43641a72f76..2d570a886866aa0cecc5972e420b1c76fb593c17 100644
--- a/packages/binary/tangle/model/transaction/payload/payload.go
+++ b/packages/binary/tangle/model/transaction/payload/payload.go
@@ -8,5 +8,7 @@ type Payload interface {
 	encoding.BinaryMarshaler
 	encoding.BinaryUnmarshaler
 
+	Bytes() []byte
 	GetType() Type
+	String() string
 }
diff --git a/packages/binary/tangle/model/transaction/test/transaction_test.go b/packages/binary/tangle/model/transaction/test/transaction_test.go
index 1ca51d61b5d7b49fcf31df68a5da4a9b1b6b8708..fdac283ef304d95d19311ea4017a5e00aa49e999 100644
--- a/packages/binary/tangle/model/transaction/test/transaction_test.go
+++ b/packages/binary/tangle/model/transaction/test/transaction_test.go
@@ -34,7 +34,7 @@ func BenchmarkVerifyDataTransactions(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		currentIndex := i
 		pool.Submit(func() {
-			if tx, err := transaction.FromBytes(transactions[currentIndex]); err != nil {
+			if tx, err, _ := transaction.FromBytes(transactions[currentIndex]); err != nil {
 				b.Error(err)
 			} else {
 				tx.VerifySignature()
diff --git a/packages/binary/tangle/model/transaction/transaction.go b/packages/binary/tangle/model/transaction/transaction.go
index 227b30954db9086f9f640dcf954bdaa7c44c9ffe..5e662b83c3aa2e8e6bf5a1a9e1d06a20fd94a43f 100644
--- a/packages/binary/tangle/model/transaction/transaction.go
+++ b/packages/binary/tangle/model/transaction/transaction.go
@@ -1,12 +1,12 @@
 package transaction
 
 import (
-	"encoding/binary"
 	"sync"
 
 	"github.com/iotaledger/hive.go/stringify"
 
 	"github.com/iotaledger/goshimmer/packages/binary/identity"
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload"
 
 	"github.com/iotaledger/hive.go/objectstorage"
@@ -60,9 +60,66 @@ func FromStorage(id []byte) (result objectstorage.StorableObject) {
 	return
 }
 
-func FromBytes(bytes []byte) (result *Transaction, err error) {
-	result = &Transaction{}
-	err = result.UnmarshalBinary(bytes)
+func FromBytes(bytes []byte, optionalTargetObject ...*Transaction) (result *Transaction, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &Transaction{}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to FromBytes")
+	}
+
+	// initialize helper
+	marshalUtil := marshalutil.New(bytes)
+
+	// read trunk transaction id
+	trunkTransactionId, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return IdFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.trunkTransactionId = trunkTransactionId.(Id)
+
+	// read branch transaction id
+	branchTransactionId, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return IdFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.branchTransactionId = branchTransactionId.(Id)
+
+	// read issuer
+	publicKeyBytes, err := marshalUtil.ReadBytes(identity.PublicKeySize)
+	if err != nil {
+		return
+	}
+	result.issuer = identity.New(publicKeyBytes)
+
+	// read payload type
+	payloadType, err := marshalUtil.ReadUint32()
+	if err != nil {
+		return
+	}
+
+	// read payload
+	payloadBytes, err := marshalUtil.ReadBytes(-identity.SignatureSize)
+	if err != nil {
+		return
+	}
+	result.payload, err = payload.GetUnmarshaler(payloadType)(payloadBytes)
+	if err != nil {
+		return
+	}
+
+	// read signature
+	copy(result.signature[:], marshalUtil.ReadRemainingBytes())
+
+	// store marshaled version
+	result.bytes = make([]byte, len(bytes))
+	copy(result.bytes, bytes)
+
+	// return the number of bytes we processed
+	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
@@ -167,91 +224,41 @@ func (transaction *Transaction) calculatePayloadId() payload.Id {
 	return blake2b.Sum512(bytes[2*IdLength:])
 }
 
-// Since transactions are immutable and do not get changed after being created, we cache the result of the marshaling.
-func (transaction *Transaction) MarshalBinary() (result []byte, err error) {
+func (transaction *Transaction) Bytes() []byte {
 	transaction.bytesMutex.RLock()
-	if transaction.bytes == nil {
-		transaction.bytesMutex.RUnlock()
-
-		transaction.bytesMutex.Lock()
-		if transaction.bytes == nil {
-			var serializedPayload []byte
-			if transaction.payload != nil {
-				if serializedPayload, err = transaction.payload.MarshalBinary(); err != nil {
-					return
-				}
-			}
-			serializedPayloadLength := len(serializedPayload)
-
-			result = make([]byte, IdLength+IdLength+identity.PublicKeySize+4+serializedPayloadLength+identity.SignatureSize)
-			offset := 0
-
-			copy(result[offset:], transaction.trunkTransactionId[:])
-			offset += IdLength
-
-			copy(result[offset:], transaction.branchTransactionId[:])
-			offset += IdLength
-
-			if transaction.issuer != nil {
-				copy(result[offset:], transaction.issuer.PublicKey)
-			}
-			offset += identity.PublicKeySize
-
-			binary.LittleEndian.PutUint32(result[offset:], transaction.payload.GetType())
-			offset += 4
-
-			if serializedPayloadLength != 0 {
-				copy(result[offset:], serializedPayload)
-				offset += serializedPayloadLength
-			}
-
-			if transaction.issuer != nil {
-				transaction.signatureMutex.Lock()
-				copy(transaction.signature[:], transaction.issuer.Sign(result[:offset]))
-				transaction.signatureMutex.Unlock()
-				copy(result[offset:], transaction.signature[:])
-			}
-			// offset += identity.SignatureSize
-
-			transaction.bytes = result
-		} else {
-			result = transaction.bytes
-		}
-		transaction.bytesMutex.Unlock()
-	} else {
-		result = transaction.bytes
+	if transaction.bytes != nil {
+		defer transaction.bytesMutex.RUnlock()
 
-		transaction.bytesMutex.RUnlock()
+		return transaction.bytes
 	}
 
-	return
-}
-
-func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) {
-	offset := 0
-
-	copy(transaction.trunkTransactionId[:], data[offset:])
-	offset += IdLength
+	transaction.bytesMutex.RUnlock()
+	transaction.bytesMutex.RLock()
+	defer transaction.bytesMutex.RUnlock()
 
-	copy(transaction.branchTransactionId[:], data[offset:])
-	offset += IdLength
+	if transaction.bytes != nil {
+		return transaction.bytes
+	}
 
-	transaction.issuer = identity.New(data[offset : offset+identity.PublicKeySize])
-	offset += identity.PublicKeySize
+	marshalUtil := marshalutil.New()
 
-	payloadType := binary.LittleEndian.Uint32(data[offset:])
-	offset += 4
+	marshalUtil.WriteBytes(transaction.trunkTransactionId.Bytes())
+	marshalUtil.WriteBytes(transaction.branchTransactionId.Bytes())
+	marshalUtil.WriteBytes(transaction.issuer.PublicKey)
+	marshalUtil.WriteUint32(transaction.payload.GetType())
+	marshalUtil.WriteBytes(transaction.payload.Bytes())
+	marshalUtil.WriteBytes(transaction.issuer.Sign(marshalUtil.Bytes()))
 
-	if transaction.payload, err = payload.GetUnmarshaler(payloadType)(data[offset : len(data)-identity.SignatureSize]); err != nil {
-		return
-	}
-	offset += len(data) - identity.SignatureSize - offset
+	return marshalUtil.Bytes()
+}
 
-	copy(transaction.signature[:], data[offset:])
-	// offset += identity.SignatureSize
+// Since transactions are immutable and do not get changed after being created, we cache the result of the marshaling.
+func (transaction *Transaction) MarshalBinary() (result []byte, err error) {
+	return transaction.Bytes(), nil
+}
 
-	transaction.bytes = make([]byte, len(data))
-	copy(transaction.bytes, data)
+func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) {
+	_, err, _ = FromBytes(data, transaction)
 
 	return
 }
diff --git a/packages/binary/tangle/transactionparser/transactionparser.go b/packages/binary/tangle/transactionparser/transactionparser.go
index f1568d49796a6b1dd9fc16917b3fdac6daeade91..8aa1c56d36ea23243587b33fdd33b69480e96885 100644
--- a/packages/binary/tangle/transactionparser/transactionparser.go
+++ b/packages/binary/tangle/transactionparser/transactionparser.go
@@ -136,7 +136,7 @@ func (transactionParser *TransactionParser) setupTransactionsFilterDataFlow() {
 }
 
 func (transactionParser *TransactionParser) parseTransaction(bytes []byte, peer *peer.Peer) {
-	if parsedTransaction, err := transaction.FromBytes(bytes); err != nil {
+	if parsedTransaction, err, _ := transaction.FromBytes(bytes); err != nil {
 		transactionParser.Events.BytesRejected.Trigger(bytes, err, peer)
 	} else {
 		transactionParser.transactionFilters[0].Filter(parsedTransaction, peer)
diff --git a/packages/binary/valuetransfers/address/address.go b/packages/binary/valuetransfers/address/address.go
index 22947afa4936af755cd8e9a0f1b204dd2cd4cb5e..17cfddba141ff76a67a3b25fa992474746ff660d 100644
--- a/packages/binary/valuetransfers/address/address.go
+++ b/packages/binary/valuetransfers/address/address.go
@@ -2,6 +2,9 @@ package address
 
 import (
 	"github.com/mr-tron/base58"
+	"golang.org/x/crypto/blake2b"
+
+	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
 )
 
 type AddressVersion = byte
@@ -16,6 +19,15 @@ func New(bytes []byte) (address Address) {
 	return
 }
 
+func FromED25519PubKey(key ed25119.PublicKey) (address Address) {
+	digest := blake2b.Sum256(key[:])
+
+	address[0] = 0
+	copy(address[1:], digest[:])
+
+	return
+}
+
 func (address *Address) GetVersion() AddressVersion {
 	return address[0]
 }
diff --git a/packages/binary/valuetransfers/coloredbalance/coloredbalance.go b/packages/binary/valuetransfers/coloredbalance/coloredbalance.go
index 26b0a485207480e384c52f644299daf5c55649a3..6d8f576bb570575d1e841549f828371c99370a32 100644
--- a/packages/binary/valuetransfers/coloredbalance/coloredbalance.go
+++ b/packages/binary/valuetransfers/coloredbalance/coloredbalance.go
@@ -44,7 +44,7 @@ func FromBytes(bytes []byte) (result *ColoredBalance, err error, consumedBytes i
 	return
 }
 
-func (balance *ColoredBalance) ToBytes() []byte {
+func (balance *ColoredBalance) Bytes() []byte {
 	marshalUtil := marshalutil.New(color.Length + marshalutil.UINT32_SIZE)
 
 	marshalUtil.WriteBytes(balance.color.Bytes())
diff --git a/packages/binary/valuetransfers/payload/transfer/inputs/inputs.go b/packages/binary/valuetransfers/payload/transfer/inputs/inputs.go
index d36935b03eb1a87859a4733605b841b488c88dce..bfb7e68840cfb082de4ac3d0269dcb2c5484223e 100644
--- a/packages/binary/valuetransfers/payload/transfer/inputs/inputs.go
+++ b/packages/binary/valuetransfers/payload/transfer/inputs/inputs.go
@@ -78,7 +78,7 @@ func (inputs *Inputs) Add(input transferoutputid.Id) *Inputs {
 	return inputs
 }
 
-func (inputs *Inputs) ToBytes() (bytes []byte) {
+func (inputs *Inputs) Bytes() (bytes []byte) {
 	marshalUtil := marshalutil.New()
 
 	marshalUtil.WriteSeek(4)
@@ -106,11 +106,9 @@ func (inputs *Inputs) ForEach(consumer func(transferOutputId transferoutputid.Id
 	})
 }
 
-func (inputs *Inputs) ForEachAddress(consumer func(currentAddress address.Address)) {
+func (inputs *Inputs) ForEachAddress(consumer func(currentAddress address.Address) bool) {
 	inputs.OrderedMap.ForEach(func(key, value interface{}) bool {
-		consumer(key.(address.Address))
-
-		return true
+		return consumer(key.(address.Address))
 	})
 }
 
diff --git a/packages/binary/valuetransfers/payload/transfer/outputs/outputs.go b/packages/binary/valuetransfers/payload/transfer/outputs/outputs.go
index 4c66d7ef0a0d2dceeb3d61000691b5bde1d9cb49..7a6d94febd64f14aa4178c2e832d296edfb1603b 100644
--- a/packages/binary/valuetransfers/payload/transfer/outputs/outputs.go
+++ b/packages/binary/valuetransfers/payload/transfer/outputs/outputs.go
@@ -3,15 +3,15 @@ package outputs
 import (
 	"github.com/iotaledger/goshimmer/packages/binary/datastructure/orderedmap"
 	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
-	address2 "github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
-	coloredbalance2 "github.com/iotaledger/goshimmer/packages/binary/valuetransfers/coloredbalance"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/coloredbalance"
 )
 
 type Outputs struct {
 	*orderedmap.OrderedMap
 }
 
-func New(outputs map[address2.Address][]*coloredbalance2.ColoredBalance) (result *Outputs) {
+func New(outputs map[address.Address][]*coloredbalance.ColoredBalance) (result *Outputs) {
 	result = &Outputs{orderedmap.New()}
 	for address, balances := range outputs {
 		result.Add(address, balances)
@@ -37,23 +37,21 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *Outputs,
 	marshalUtil := marshalutil.New(bytes)
 
 	// read number of addresses in the outputs
-	addressCount, addressCountErr := marshalUtil.ReadUint32()
-	if addressCountErr != nil {
-		err = addressCountErr
-
+	addressCount, err := marshalUtil.ReadUint32()
+	if err != nil {
 		return
 	}
 
 	// iterate the corresponding times and collect addresses + their details
 	for i := uint32(0); i < addressCount; i++ {
 		// read address
-		addressBytes, addressErr := marshalUtil.ReadBytes(address2.Length)
+		addressBytes, addressErr := marshalUtil.ReadBytes(address.Length)
 		if addressErr != nil {
 			err = addressErr
 
 			return
 		}
-		address := address2.New(addressBytes)
+		address := address.New(addressBytes)
 
 		// read number of balances in the outputs
 		balanceCount, balanceCountErr := marshalUtil.ReadUint32()
@@ -64,16 +62,16 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *Outputs,
 		}
 
 		// iterate the corresponding times and collect balances
-		coloredBalances := make([]*coloredbalance2.ColoredBalance, balanceCount)
+		coloredBalances := make([]*coloredbalance.ColoredBalance, balanceCount)
 		for j := uint32(0); j < balanceCount; j++ {
-			coloredBalance, coloredBalanceErr := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return coloredbalance2.FromBytes(data) })
+			coloredBalance, coloredBalanceErr := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return coloredbalance.FromBytes(data) })
 			if coloredBalanceErr != nil {
 				err = coloredBalanceErr
 
 				return
 			}
 
-			coloredBalances[j] = coloredBalance.(*coloredbalance2.ColoredBalance)
+			coloredBalances[j] = coloredBalance.(*coloredbalance.ColoredBalance)
 		}
 
 		// add the gathered information as an output
@@ -86,15 +84,15 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *Outputs,
 	return
 }
 
-func (outputs *Outputs) Add(address address2.Address, balances []*coloredbalance2.ColoredBalance) *Outputs {
+func (outputs *Outputs) Add(address address.Address, balances []*coloredbalance.ColoredBalance) *Outputs {
 	outputs.Set(address, balances)
 
 	return outputs
 }
 
-func (outputs *Outputs) ForEach(consumer func(address address2.Address, balances []*coloredbalance2.ColoredBalance)) {
+func (outputs *Outputs) ForEach(consumer func(address address.Address, balances []*coloredbalance.ColoredBalance)) {
 	outputs.OrderedMap.ForEach(func(key, value interface{}) bool {
-		consumer(key.(address2.Address), value.([]*coloredbalance2.ColoredBalance))
+		consumer(key.(address.Address), value.([]*coloredbalance.ColoredBalance))
 
 		return true
 	})
@@ -110,12 +108,12 @@ func (outputs *Outputs) Bytes() []byte {
 	}
 
 	marshalUtil.WriteUint32(uint32(outputs.Size()))
-	outputs.ForEach(func(address address2.Address, balances []*coloredbalance2.ColoredBalance) {
+	outputs.ForEach(func(address address.Address, balances []*coloredbalance.ColoredBalance) {
 		marshalUtil.WriteBytes(address.ToBytes())
 		marshalUtil.WriteUint32(uint32(len(balances)))
 
 		for _, balance := range balances {
-			marshalUtil.WriteBytes(balance.ToBytes())
+			marshalUtil.WriteBytes(balance.Bytes())
 		}
 	})
 
@@ -129,7 +127,7 @@ func (outputs *Outputs) String() string {
 
 	result := "[\n"
 	empty := true
-	outputs.ForEach(func(address address2.Address, balances []*coloredbalance2.ColoredBalance) {
+	outputs.ForEach(func(address address.Address, balances []*coloredbalance.ColoredBalance) {
 		empty = false
 
 		result += "    " + address.String() + ": [\n"
diff --git a/packages/binary/valuetransfers/payload/transfer/signatures/ed25519.go b/packages/binary/valuetransfers/payload/transfer/signatures/ed25519.go
new file mode 100644
index 0000000000000000000000000000000000000000..17cdc17d78cfa4f7d1ac016e5a11f231f57fe4b3
--- /dev/null
+++ b/packages/binary/valuetransfers/payload/transfer/signatures/ed25519.go
@@ -0,0 +1,134 @@
+package signatures
+
+import (
+	"fmt"
+
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
+	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
+)
+
+// region PUBLIC API ///////////////////////////////////////////////////////////////////////////////////////////////////
+
+const (
+	// every signature scheme has a version byte associated to it.
+	VERSION_ED25519 = byte(1)
+)
+
+// ED25519 creates an instance of a signature scheme, that is used to sign the corresponding address.
+func ED25519(keyPair ed25119.KeyPair) SignatureScheme {
+	return &ed25519SignatureScheme{
+		keyPair: keyPair,
+	}
+}
+
+// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// region signature scheme implementation //////////////////////////////////////////////////////////////////////////////
+
+// ed25519SignatureScheme defines an interface for ED25519 elliptic curve signatures.
+type ed25519SignatureScheme struct {
+	keyPair ed25119.KeyPair
+}
+
+// Version returns the version byte that is associated to this signature scheme.
+func (signatureScheme *ed25519SignatureScheme) Version() byte {
+	return VERSION_ED25519
+}
+
+// Address returns the address that this signature scheme instance is securing.
+func (signatureScheme *ed25519SignatureScheme) Address() address.Address {
+	return address.FromED25519PubKey(signatureScheme.keyPair.PublicKey)
+}
+
+// Sign creates a valid signature for the given data according to the signature scheme implementation.
+func (signatureScheme *ed25519SignatureScheme) Sign(data []byte) Signature {
+	return &ed25519Signature{
+		publicKey: signatureScheme.keyPair.PublicKey,
+		signature: signatureScheme.keyPair.PrivateKey.Sign(data),
+	}
+}
+
+// interface contract (allow the compiler to check if the implementation has all of the required methods).
+var _ SignatureScheme = &ed25519SignatureScheme{}
+
+// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// region signature implementation /////////////////////////////////////////////////////////////////////////////////////
+
+// ed25519Signature represents a signature for an addresses that uses elliptic curve cryptography.
+type ed25519Signature struct {
+	publicKey ed25119.PublicKey
+	signature ed25119.Signature
+}
+
+// ed25519SignatureFromBytes unmarshals an ed25519 signatures from a sequence of bytes.
+// It either creates a new signature or fills the optionally provided object with the parsed information.
+func ed25519SignatureFromBytes(bytes []byte, optionalTargetObject ...*ed25519Signature) (result *ed25519Signature, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &ed25519Signature{}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to ed25519SignatureFromBytes")
+	}
+
+	// initialize helper
+	marshalUtil := marshalutil.New(bytes)
+
+	// read version
+	versionByte, err := marshalUtil.ReadByte()
+	if err != nil {
+		return
+	} else if versionByte != VERSION_ED25519 {
+		err = fmt.Errorf("invalid version byte when parsing ed25519 signature")
+
+		return
+	}
+
+	// read public key
+	publicKey, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return ed25119.PublicKeyFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.publicKey = publicKey.(ed25119.PublicKey)
+
+	// read signature
+	signature, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return ed25119.SignatureFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.signature = signature.(ed25119.Signature)
+
+	// return the number of bytes we processed
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+// IsValid returns true if the signature is valid for the given data.
+func (signature *ed25519Signature) IsValid(signedData []byte) bool {
+	return signature.publicKey.VerifySignature(signedData, signature.signature)
+}
+
+// Bytes returns a marshaled version of the signature.
+func (signature *ed25519Signature) Bytes() []byte {
+	marshalUtil := marshalutil.New(1 + ed25119.PublicKeySize + ed25119.SignatureSize)
+	marshalUtil.WriteByte(VERSION_ED25519)
+	marshalUtil.WriteBytes(signature.publicKey[:])
+	marshalUtil.WriteBytes(signature.signature[:])
+
+	return marshalUtil.Bytes()
+}
+
+// Address returns the address, that this signature signs.
+func (signature *ed25519Signature) Address() address.Address {
+	return address.FromED25519PubKey(signature.publicKey)
+}
+
+// interface contract (allow the compiler to check if the implementation has all of the required methods).
+var _ Signature = &ed25519Signature{}
+
+// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/binary/valuetransfers/payload/transfer/signatures/interfaces.go b/packages/binary/valuetransfers/payload/transfer/signatures/interfaces.go
new file mode 100644
index 0000000000000000000000000000000000000000..9b28078ff953206e6c3aedcb12ca36e7b59d66db
--- /dev/null
+++ b/packages/binary/valuetransfers/payload/transfer/signatures/interfaces.go
@@ -0,0 +1,27 @@
+package signatures
+
+import "github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
+
+// SignatureScheme defines an interface for different signature generation methods (i.e. ED25519, WOTS, and so on ...).
+type SignatureScheme interface {
+	// Version returns the version byte that is associated to this signature scheme.
+	Version() byte
+
+	// Address returns the address that this signature scheme instance is securing.
+	Address() address.Address
+
+	// Sign creates a valid signature for the given data according to the signature scheme implementation.
+	Sign(data []byte) Signature
+}
+
+// Signature defines an interface for an address signature generated by the corresponding signature scheme.
+type Signature interface {
+	// IsValid returns true if the signature is valid for the given data.
+	IsValid(signedData []byte) bool
+
+	// Bytes returns a marshaled version of the signature.
+	Bytes() []byte
+
+	// Address returns the address, that this signature signs.
+	Address() address.Address
+}
diff --git a/packages/binary/valuetransfers/payload/transfer/signatures/signatures.go b/packages/binary/valuetransfers/payload/transfer/signatures/signatures.go
index 87f18aacd027ce65b3eafd1b9e772e489e324e93..f5cfee2cfe03550a9282eefabcaf2ea6617eacc2 100644
--- a/packages/binary/valuetransfers/payload/transfer/signatures/signatures.go
+++ b/packages/binary/valuetransfers/payload/transfer/signatures/signatures.go
@@ -1,4 +1,117 @@
 package signatures
 
+import (
+	"github.com/iotaledger/goshimmer/packages/binary/datastructure/orderedmap"
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
+)
+
+// Signatures represents a container for the address signatures of a value transfer.
+// It internally manages the list of signatures as an ordered map, so that the serialization order is deterministic and
+// produces the same sequence of bytes during marshaling and unmarshaling.
 type Signatures struct {
+	orderedMap *orderedmap.OrderedMap
+}
+
+// New creates an empty container for the address signatures of a value transfer.
+func New() *Signatures {
+	return &Signatures{
+		orderedMap: orderedmap.New(),
+	}
+}
+
+// FromBytes unmarshals a container with signatures from a sequence of bytes.
+// It either creates a new container or fills the optionally provided container with the parsed information.
+func FromBytes(bytes []byte, optionalTargetObject ...*Signatures) (result *Signatures, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &Signatures{orderedMap: orderedmap.New()}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to FromBytes")
+	}
+
+	// initialize helper
+	marshalUtil := marshalutil.New(bytes)
+
+	// read version
+	versionByte, err := marshalUtil.ReadByte()
+	if err != nil {
+		return
+	}
+
+	// 0 byte encodes the end of the signatures
+	for versionByte != 0 {
+		// perform signature scheme specific decoding
+		switch versionByte {
+		case VERSION_ED25519:
+			marshalUtil.ReadSeek(-1)
+			signature, signatureErr := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return ed25519SignatureFromBytes(data) })
+			if signatureErr != nil {
+				err = signatureErr
+
+				return
+			}
+			typeCastedSignature := signature.(Signature)
+
+			result.orderedMap.Set(typeCastedSignature.Address(), typeCastedSignature)
+		}
+
+		// read version of next signature
+		if versionByte, err = marshalUtil.ReadByte(); err != nil {
+			return
+		}
+	}
+
+	// return the number of bytes we processed
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+func (signatures *Signatures) Add(address address.Address, signature Signature) {
+	signatures.orderedMap.Set(address, signature)
+}
+
+func (signatures *Signatures) Get(address address.Address) (Signature, bool) {
+	signature, exists := signatures.orderedMap.Get(address)
+	if !exists {
+		return nil, false
+	}
+
+	return signature.(Signature), exists
+}
+
+// Size returns the amount of signatures in this container.
+func (signatures *Signatures) Size() int {
+	return signatures.orderedMap.Size()
+}
+
+// ForEach iterates through all signatures, calling the consumer for every found entry.
+// The iteration can be aborted by the consumer returning false
+func (signatures *Signatures) ForEach(consumer func(address address.Address, signature Signature) bool) {
+	signatures.orderedMap.ForEach(func(key, value interface{}) bool {
+		return consumer(key.(address.Address), value.(Signature))
+	})
+}
+
+// Bytes marshals the signatures into a sequence of bytes.
+func (signatures *Signatures) Bytes() []byte {
+	// initialize helper
+	marshalUtil := marshalutil.New()
+
+	// iterate through signatures and dump them
+	signatures.ForEach(func(address address.Address, signature Signature) bool {
+		marshalUtil.WriteBytes(signature.Bytes())
+
+		return true
+	})
+
+	// trailing 0 to indicate the end of signatures
+	marshalUtil.WriteByte(0)
+
+	// return result
+	return marshalUtil.Bytes()
 }
diff --git a/packages/binary/valuetransfers/payload/transfer/signatures/signatures_test.go b/packages/binary/valuetransfers/payload/transfer/signatures/signatures_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a4aca5092e78ebceb620719f23be35249aee5779
--- /dev/null
+++ b/packages/binary/valuetransfers/payload/transfer/signatures/signatures_test.go
@@ -0,0 +1,48 @@
+package signatures
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
+)
+
+func TestSignatures(t *testing.T) {
+	dataToSign := []byte("test")
+
+	address1SigScheme := ED25519(ed25119.GenerateKeyPair())
+	address2SigScheme := ED25519(ed25119.GenerateKeyPair())
+
+	signatures := New()
+	signatures.Add(address1SigScheme.Address(), address1SigScheme.Sign(dataToSign))
+	signatures.Add(address2SigScheme.Address(), address2SigScheme.Sign(dataToSign))
+
+	assert.Equal(t, 2, signatures.Size())
+
+	signatures.Add(address1SigScheme.Address(), address1SigScheme.Sign(dataToSign))
+
+	assert.Equal(t, 2, signatures.Size())
+
+	signatures.ForEach(func(address address.Address, signature Signature) bool {
+		assert.Equal(t, true, signature.IsValid(dataToSign))
+
+		return true
+	})
+
+	clonedSignatures, err, _ := FromBytes(signatures.Bytes())
+	if err != nil {
+		t.Error(err)
+
+		return
+	}
+
+	assert.Equal(t, 2, clonedSignatures.Size())
+
+	clonedSignatures.ForEach(func(address address.Address, signature Signature) bool {
+		assert.Equal(t, true, signature.IsValid(dataToSign))
+
+		return true
+	})
+}
diff --git a/packages/binary/valuetransfers/payload/transfer/transfer.go b/packages/binary/valuetransfers/payload/transfer/transfer.go
index ab9f3bfafc6002412e26c95729c49a8cf970b398..fd041ce5481d164b84964cc7efc5c073a7756803 100644
--- a/packages/binary/valuetransfers/payload/transfer/transfer.go
+++ b/packages/binary/valuetransfers/payload/transfer/transfer.go
@@ -10,7 +10,7 @@ import (
 	"golang.org/x/crypto/blake2b"
 
 	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
-	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/id"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/inputs"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/outputs"
@@ -41,8 +41,9 @@ type Transfer struct {
 
 func New(inputs *inputs.Inputs, outputs *outputs.Outputs) *Transfer {
 	return &Transfer{
-		inputs:  inputs,
-		outputs: outputs,
+		inputs:     inputs,
+		outputs:    outputs,
+		signatures: signatures.New(),
 	}
 }
 
@@ -74,8 +75,25 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Transfer) (result *Transfe
 	}
 	result.outputs = parsedOutputs.(*outputs.Outputs)
 
+	// store essence bytes
+	essenceBytesCount := marshalUtil.ReadOffset()
+	result.essenceBytes = make([]byte, essenceBytesCount)
+	copy(result.essenceBytes, bytes[:essenceBytesCount])
+
+	// unmarshal outputs
+	parsedSignatures, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return signatures.FromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.signatures = parsedSignatures.(*signatures.Signatures)
+
+	// store signature bytes
+	signatureBytesCount := marshalUtil.ReadOffset() - essenceBytesCount
+	result.signatureBytes = make([]byte, signatureBytesCount)
+	copy(result.signatureBytes, bytes[essenceBytesCount:essenceBytesCount+signatureBytesCount])
+
 	// return the number of bytes we processed
-	consumedBytes = marshalUtil.ReadOffset()
+	consumedBytes = essenceBytesCount + signatureBytesCount
 
 	// store bytes, so we don't have to marshal manually
 	result.bytes = bytes[:consumedBytes]
@@ -84,10 +102,10 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Transfer) (result *Transfe
 }
 
 func FromStorage(key []byte) *Transfer {
-	id := id.New(key)
+	transferId := id.New(key)
 
 	return &Transfer{
-		id: &id,
+		id: &transferId,
 	}
 }
 
@@ -122,8 +140,81 @@ func (transfer *Transfer) GetId() id.Id {
 	return transferId
 }
 
+func (transfer *Transfer) SignaturesValid() bool {
+	signaturesValid := true
+	transfer.inputs.ForEachAddress(func(address address.Address) bool {
+		if signature, exists := transfer.signatures.Get(address); !exists || !signature.IsValid(transfer.EssenceBytes()) {
+			signaturesValid = false
+
+			return false
+		}
+
+		return true
+	})
+
+	return signaturesValid
+}
+
+func (transfer *Transfer) EssenceBytes() []byte {
+	// acquire read lock on essenceBytes
+	transfer.essenceBytesMutex.RLock()
+
+	// return essenceBytes if the object has been marshaled already
+	if transfer.essenceBytes != nil {
+		defer transfer.essenceBytesMutex.RUnlock()
+
+		return transfer.essenceBytes
+	}
+
+	// switch to write lock
+	transfer.essenceBytesMutex.RUnlock()
+	transfer.essenceBytesMutex.Lock()
+	defer transfer.essenceBytesMutex.Unlock()
+
+	// return essenceBytes if the object has been marshaled in the mean time
+	if essenceBytes := transfer.essenceBytes; essenceBytes != nil {
+		return essenceBytes
+	}
+
+	// create marshal helper
+	marshalUtil := marshalutil.New()
+
+	// marshal inputs
+	marshalUtil.WriteBytes(transfer.inputs.Bytes())
+
+	// marshal outputs
+	marshalUtil.WriteBytes(transfer.outputs.Bytes())
+
+	// store marshaled result
+	transfer.essenceBytes = marshalUtil.Bytes()
+
+	return transfer.essenceBytes
+}
+
+func (transfer *Transfer) SignatureBytes() []byte {
+	transfer.signatureBytesMutex.RLock()
+	if transfer.signatureBytes != nil {
+		defer transfer.signatureBytesMutex.RUnlock()
+
+		return transfer.signatureBytes
+	}
+
+	transfer.signatureBytesMutex.RUnlock()
+	transfer.signatureBytesMutex.Lock()
+	defer transfer.signatureBytesMutex.Unlock()
+
+	if transfer.signatureBytes != nil {
+		return transfer.signatureBytes
+	}
+
+	// generate signatures
+	transfer.signatureBytes = transfer.signatures.Bytes()
+
+	return transfer.signatureBytes
+}
+
 func (transfer *Transfer) Bytes() []byte {
-	// acquired read lock on bytes
+	// acquire read lock on bytes
 	transfer.bytesMutex.RLock()
 
 	// return bytes if the object has been marshaled already
@@ -146,11 +237,11 @@ func (transfer *Transfer) Bytes() []byte {
 	// create marshal helper
 	marshalUtil := marshalutil.New()
 
-	// marshal inputs
-	marshalUtil.WriteBytes(transfer.inputs.ToBytes())
+	// marshal essence bytes
+	marshalUtil.WriteBytes(transfer.EssenceBytes())
 
-	// marshal outputs
-	marshalUtil.WriteBytes(transfer.outputs.Bytes())
+	// marshal signature bytes
+	marshalUtil.WriteBytes(transfer.SignatureBytes())
 
 	// store marshaled result
 	transfer.bytes = marshalUtil.Bytes()
@@ -158,8 +249,10 @@ func (transfer *Transfer) Bytes() []byte {
 	return transfer.bytes
 }
 
-func (transfer *Transfer) Sign(pair ed25119.KeyPair) {
-	//transfer.signatures[pair.PublicKey] = pair.PrivateKey.Sign(transfer.Bytes())
+func (transfer *Transfer) Sign(signature signatures.SignatureScheme) *Transfer {
+	transfer.signatures.Add(signature.Address(), signature.Sign(transfer.EssenceBytes()))
+
+	return transfer
 }
 
 func (transfer *Transfer) String() string {
diff --git a/packages/binary/valuetransfers/test/payload_test.go b/packages/binary/valuetransfers/test/payload_test.go
index ae7cc819511c3d4d7a9ea140afdca86508d679ae..6a91a62837450552a8e74e7a80d48dcaabaf777e 100644
--- a/packages/binary/valuetransfers/test/payload_test.go
+++ b/packages/binary/valuetransfers/test/payload_test.go
@@ -4,7 +4,10 @@ import (
 	"fmt"
 	"testing"
 
+	"github.com/stretchr/testify/assert"
+
 	"github.com/iotaledger/goshimmer/packages/binary/identity"
+	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/address"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/coloredbalance"
@@ -15,6 +18,7 @@ import (
 	transferid "github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/id"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/inputs"
 	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/outputs"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfers/payload/transfer/signatures"
 	transferoutputid "github.com/iotaledger/goshimmer/packages/binary/valuetransfers/transferoutput/id"
 )
 
@@ -66,14 +70,16 @@ func ExamplePayload() {
 }
 
 func TestPayload(t *testing.T) {
+	addressKeyPair1 := ed25119.GenerateKeyPair()
+	addressKeyPair2 := ed25119.GenerateKeyPair()
 
 	originalPayload := valuepayload.New(
 		payloadid.Empty,
 		payloadid.Empty,
 		transfer.New(
 			inputs.New(
-				transferoutputid.New(address.New([]byte("input_address1")), transferid.New([]byte("transfer1"))),
-				transferoutputid.New(address.New([]byte("input_address2")), transferid.New([]byte("transfer2"))),
+				transferoutputid.New(address.FromED25519PubKey(addressKeyPair1.PublicKey), transferid.New([]byte("transfer1"))),
+				transferoutputid.New(address.FromED25519PubKey(addressKeyPair2.PublicKey), transferid.New([]byte("transfer2"))),
 			),
 
 			outputs.New(map[address.Address][]*coloredbalance.ColoredBalance{
@@ -81,17 +87,32 @@ func TestPayload(t *testing.T) {
 					coloredbalance.New(color.IOTA, 1337),
 				},
 			}),
+		).Sign(
+			signatures.ED25519(addressKeyPair1),
 		),
 	)
 
-	clonedPayload, err, _ := valuepayload.FromBytes(originalPayload.Bytes())
+	assert.Equal(t, false, originalPayload.GetTransfer().SignaturesValid())
+
+	originalPayload.GetTransfer().Sign(
+		signatures.ED25519(addressKeyPair2),
+	)
+
+	assert.Equal(t, true, originalPayload.GetTransfer().SignaturesValid())
+
+	clonedPayload1, err, _ := valuepayload.FromBytes(originalPayload.Bytes())
 	if err != nil {
 		panic(err)
 	}
 
-	fmt.Println(originalPayload)
-	fmt.Println(clonedPayload)
+	assert.Equal(t, originalPayload.GetId(), clonedPayload1.GetId())
+	assert.Equal(t, true, clonedPayload1.GetTransfer().SignaturesValid())
+
+	clonedPayload2, err, _ := valuepayload.FromBytes(clonedPayload1.Bytes())
+	if err != nil {
+		panic(err)
+	}
 
-	fmt.Println(originalPayload.GetId())
-	fmt.Println(clonedPayload.GetId())
+	assert.Equal(t, originalPayload.GetId(), clonedPayload2.GetId())
+	assert.Equal(t, true, clonedPayload2.GetTransfer().SignaturesValid())
 }
diff --git a/packages/gossip/manager.go b/packages/gossip/manager.go
index e28c81afda3211d546a8f865ec6783a70348523c..24b72a251b8c507e86297dcf0bfa3e866d82489f 100644
--- a/packages/gossip/manager.go
+++ b/packages/gossip/manager.go
@@ -256,7 +256,11 @@ func (m *Manager) handlePacket(data []byte, p *peer.Peer) error {
 		}
 		m.log.Debugw("received message", "type", "TRANSACTION_REQUEST", "id", p.ID())
 		// do something
-		tx, err := m.getTransaction(transaction.NewId(msg.GetHash()))
+		txId, err, _ := transaction.IdFromBytes(msg.GetHash())
+		if err != nil {
+			m.log.Debugw("error getting transaction", "hash", msg.GetHash(), "err", err)
+		}
+		tx, err := m.getTransaction(txId)
 		if err != nil {
 			m.log.Debugw("error getting transaction", "hash", msg.GetHash(), "err", err)
 		} else {
diff --git a/plugins/spa/explorer_routes.go b/plugins/spa/explorer_routes.go
index c3de4085e28c7838617d4ed587daf2fab5e858bc..e98cccbbd4e4c9c6672c17b6faabe8d97ac146be 100644
--- a/plugins/spa/explorer_routes.go
+++ b/plugins/spa/explorer_routes.go
@@ -4,8 +4,6 @@ import (
 	"net/http"
 	"sync"
 
-	"github.com/mr-tron/base58"
-
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
 	"github.com/iotaledger/goshimmer/plugins/tangle"
 
@@ -57,22 +55,9 @@ type SearchResult struct {
 	Milestone *ExplorerTx     `json:"milestone"`
 }
 
-func transactionIdFromString(transactionId string) (transaction.Id, error) {
-	// TODO: CHECK LENGTH
-
-	transactionIdBytes, err := base58.Decode(transactionId)
-	if err != nil {
-		return transaction.EmptyId, err
-	}
-
-	// TODO: REMOVE CHECKSUM FROM STRING
-
-	return transaction.NewId(transactionIdBytes), nil
-}
-
 func setupExplorerRoutes(routeGroup *echo.Group) {
 	routeGroup.GET("/tx/:hash", func(c echo.Context) (err error) {
-		transactionId, err := transactionIdFromString(c.Param("hash"))
+		transactionId, err := transaction.NewId(c.Param("hash"))
 		if err != nil {
 			return
 		}
@@ -106,7 +91,7 @@ func setupExplorerRoutes(routeGroup *echo.Group) {
 		go func() {
 			defer wg.Done()
 
-			transactionId, err := transactionIdFromString(search)
+			transactionId, err := transaction.NewId(search)
 			if err != nil {
 				return
 			}