diff --git a/go.mod b/go.mod
index a838712d43511b98bdcd369ec46a791d14904901..980d0c687728de123020e38bb4e4da3ab4a70300 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2
 	github.com/googollee/go-socket.io v1.4.3-0.20191204093753-683f8725b6d0
 	github.com/gorilla/websocket v1.4.1
-	github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1
+	github.com/iotaledger/hive.go v0.0.0-20200325224052-ac4d38108211
 	github.com/iotaledger/iota.go v1.0.0-beta.14
 	github.com/labstack/echo v3.3.10+incompatible
 	github.com/labstack/gommon v0.3.0 // indirect
diff --git a/go.sum b/go.sum
index 9fca25e7e54c8f86f4d906784e0aa79f4f34d934..f6d9cee1c09a466bd97fb74cbe5a13201f4a93e7 100644
--- a/go.sum
+++ b/go.sum
@@ -130,10 +130,8 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d h1:bwrSVMHIVROkg6wkdg2MmMRrzRwGORjNBl7LHJzp3+0=
-github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc=
-github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1 h1:ActziRcYMPDnccHya7NKtwsPCIL5B9WcSE/g6ZFcAew=
-github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc=
+github.com/iotaledger/hive.go v0.0.0-20200325224052-ac4d38108211 h1:ckZnjlKHCqgsG6jV5EEyI4uSXElOJxLN1fwQHc4r+eM=
+github.com/iotaledger/hive.go v0.0.0-20200325224052-ac4d38108211/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc=
 github.com/iotaledger/iota.go v1.0.0-beta.9/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8=
 github.com/iotaledger/iota.go v1.0.0-beta.14 h1:Oeb28MfBuJEeXcGrLhTCJFtbsnc8y1u7xidsAmiOD5A=
 github.com/iotaledger/iota.go v1.0.0-beta.14/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8=
diff --git a/packages/binary/storageprefix/storageprefix.go b/packages/binary/storageprefix/storageprefix.go
index d288fb2db1a15ff0d9245d8c2f8748d401534acc..0c960b0ac2102861550b75f15b0f84c86393497e 100644
--- a/packages/binary/storageprefix/storageprefix.go
+++ b/packages/binary/storageprefix/storageprefix.go
@@ -12,9 +12,11 @@ var (
 	ValueTransferPayloadMetadata = []byte{6}
 	ValueTransferApprover        = []byte{7}
 	ValueTransferMissingPayload  = []byte{8}
+	ValueTransferAttachment      = []byte{9}
+	ValueTransferConsumer        = []byte{10}
 
-	LedgerStateTransferOutput        = []byte{9}
-	LedgerStateTransferOutputBooking = []byte{10}
-	LedgerStateReality               = []byte{11}
-	LedgerStateConflictSet           = []byte{12}
+	LedgerStateTransferOutput        = []byte{11}
+	LedgerStateTransferOutputBooking = []byte{12}
+	LedgerStateReality               = []byte{13}
+	LedgerStateConflictSet           = []byte{14}
 )
diff --git a/packages/binary/tangle/model/approver/approver.go b/packages/binary/tangle/model/approver/approver.go
index 23c0842be18b328762caafb230a0025868b4ca8b..b6545c6c4a65fb2ea821d9b33322def2f267e6e3 100644
--- a/packages/binary/tangle/model/approver/approver.go
+++ b/packages/binary/tangle/model/approver/approver.go
@@ -27,7 +27,7 @@ func New(referencedTransaction message.Id, approvingTransaction message.Id) *App
 	return approver
 }
 
-func FromStorage(id []byte) (result objectstorage.StorableObject) {
+func StorableObjectFromKey(id []byte) (result objectstorage.StorableObject, err error) {
 	approver := &Approver{
 		storageKey: make([]byte, message.IdLength+message.IdLength),
 	}
@@ -35,10 +35,10 @@ func FromStorage(id []byte) (result objectstorage.StorableObject) {
 	copy(approver.approvingTransaction[:], id[message.IdLength:])
 	copy(approver.storageKey, id)
 
-	return approver
+	return approver, nil
 }
 
-func (approver *Approver) GetStorageKey() []byte {
+func (approver *Approver) ObjectStorageKey() []byte {
 	return approver.storageKey
 }
 
@@ -50,10 +50,10 @@ func (approver *Approver) Update(other objectstorage.StorableObject) {
 	panic("approvers should never be overwritten and only stored once to optimize IO")
 }
 
-func (approver *Approver) MarshalBinary() (result []byte, err error) {
+func (approver *Approver) ObjectStorageValue() (result []byte) {
 	return
 }
 
-func (approver *Approver) UnmarshalBinary(data []byte) (err error) {
+func (approver *Approver) UnmarshalObjectStorageValue(data []byte) (err error) {
 	return
 }
diff --git a/packages/binary/tangle/model/message/payload/data/data.go b/packages/binary/tangle/model/message/payload/data/data.go
index 70efdcfcdaa7b98f2171108ba85cab469851d018..74d74a2e8d877630874ff0fcf130a3fb757caf98 100644
--- a/packages/binary/tangle/model/message/payload/data/data.go
+++ b/packages/binary/tangle/model/message/payload/data/data.go
@@ -55,7 +55,7 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Data) (result *Data, err e
 	return
 }
 
-func (dataPayload *Data) GetType() payload.Type {
+func (dataPayload *Data) Type() payload.Type {
 	return dataPayload.payloadType
 }
 
@@ -69,7 +69,7 @@ func (dataPayload *Data) Bytes() []byte {
 	marshalUtil := marshalutil.New()
 
 	// marshal the payload specific information
-	marshalUtil.WriteUint32(dataPayload.GetType())
+	marshalUtil.WriteUint32(dataPayload.Type())
 	marshalUtil.WriteUint32(uint32(len(dataPayload.data)))
 	marshalUtil.WriteBytes(dataPayload.data[:])
 
@@ -77,16 +77,12 @@ func (dataPayload *Data) Bytes() []byte {
 	return marshalUtil.Bytes()
 }
 
-func (dataPayload *Data) UnmarshalBinary(data []byte) (err error) {
+func (dataPayload *Data) Unmarshal(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())),
@@ -98,7 +94,7 @@ func GenericPayloadUnmarshalerFactory(payloadType payload.Type) payload.Unmarsha
 		payload = &Data{
 			payloadType: payloadType,
 		}
-		err = payload.UnmarshalBinary(data)
+		err = payload.Unmarshal(data)
 
 		return
 	}
diff --git a/packages/binary/tangle/model/message/payload/payload.go b/packages/binary/tangle/model/message/payload/payload.go
index 06d0d43912b9889493f0a8ba1d72cf7adaed5fec..e9300f5ae055b3861e65c4b899ce844912a6456e 100644
--- a/packages/binary/tangle/model/message/payload/payload.go
+++ b/packages/binary/tangle/model/message/payload/payload.go
@@ -1,17 +1,13 @@
 package payload
 
 import (
-	"encoding"
-
 	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
 )
 
 type Payload interface {
-	encoding.BinaryMarshaler
-	encoding.BinaryUnmarshaler
-
+	Type() Type
 	Bytes() []byte
-	GetType() Type
+	Unmarshal(bytes []byte) error
 	String() string
 }
 
diff --git a/packages/binary/tangle/model/message/test/transaction_test.go b/packages/binary/tangle/model/message/test/transaction_test.go
index 357ec1ba1978454ed0581d9835c55e1f79972d00..be5a61ffe8d24cb5c5ccfedeeecae19325cd6ca7 100644
--- a/packages/binary/tangle/model/message/test/transaction_test.go
+++ b/packages/binary/tangle/model/message/test/transaction_test.go
@@ -23,11 +23,7 @@ func BenchmarkVerifyDataTransactions(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		tx := message.New(message.EmptyId, message.EmptyId, ed25119.GenerateKeyPair(), time.Now(), 0, data.New([]byte("some data")))
 
-		if marshaledTransaction, err := tx.MarshalBinary(); err != nil {
-			b.Error(err)
-		} else {
-			transactions[i] = marshaledTransaction
-		}
+		transactions[i] = tx.Bytes()
 	}
 
 	b.ResetTimer()
diff --git a/packages/binary/tangle/model/message/transaction.go b/packages/binary/tangle/model/message/transaction.go
index ff3c9c362cdcc4f42e6fb9c6a00d40e9454cd84b..a8d99558c2900024f55cc32c6fa63a48f864b964 100644
--- a/packages/binary/tangle/model/message/transaction.go
+++ b/packages/binary/tangle/model/message/transaction.go
@@ -59,7 +59,7 @@ func New(trunkTransactionId Id, branchTransactionId Id, issuerKeyPair ed25119.Ke
 
 // Get's called when we restore a transaction from storage. The bytes and the content will be unmarshaled by an external
 // caller (the objectStorage factory).
-func FromStorage(id []byte) (result objectstorage.StorableObject) {
+func StorableObjectFromKey(id []byte) (result objectstorage.StorableObject, err error) {
 	var transactionId Id
 	copy(transactionId[:], id)
 
@@ -249,17 +249,17 @@ func (transaction *Transaction) Bytes() []byte {
 }
 
 // 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
+func (transaction *Transaction) ObjectStorageValue() []byte {
+	return transaction.Bytes()
 }
 
-func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) {
+func (transaction *Transaction) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = FromBytes(data, transaction)
 
 	return
 }
 
-func (transaction *Transaction) GetStorageKey() []byte {
+func (transaction *Transaction) ObjectStorageKey() []byte {
 	transactionId := transaction.GetId()
 
 	return transactionId[:]
diff --git a/packages/binary/tangle/model/missingtransaction/missingtransaction.go b/packages/binary/tangle/model/missingtransaction/missingtransaction.go
index 64baa95c546c79f158ae50f4ec14fd4dcfc6b722..a4fc5871dd3b93ee3a122da968c045050b742949 100644
--- a/packages/binary/tangle/model/missingtransaction/missingtransaction.go
+++ b/packages/binary/tangle/model/missingtransaction/missingtransaction.go
@@ -21,11 +21,11 @@ func New(transactionId message.Id) *MissingTransaction {
 	}
 }
 
-func FromStorage(key []byte) objectstorage.StorableObject {
+func StorableObjectFromKey(key []byte) (objectstorage.StorableObject, error) {
 	result := &MissingTransaction{}
 	copy(result.transactionId[:], key)
 
-	return result
+	return result, nil
 }
 
 func (missingTransaction *MissingTransaction) GetTransactionId() message.Id {
@@ -36,18 +36,23 @@ func (missingTransaction *MissingTransaction) GetMissingSince() time.Time {
 	return missingTransaction.missingSince
 }
 
-func (missingTransaction *MissingTransaction) GetStorageKey() []byte {
-	return missingTransaction.transactionId[:]
-}
-
 func (missingTransaction *MissingTransaction) Update(other objectstorage.StorableObject) {
 	panic("missing transactions should never be overwritten and only stored once to optimize IO")
 }
 
-func (missingTransaction *MissingTransaction) MarshalBinary() (result []byte, err error) {
-	return missingTransaction.missingSince.MarshalBinary()
+func (missingTransaction *MissingTransaction) ObjectStorageKey() []byte {
+	return missingTransaction.transactionId[:]
+}
+
+func (missingTransaction *MissingTransaction) ObjectStorageValue() (result []byte) {
+	result, err := missingTransaction.missingSince.MarshalBinary()
+	if err != nil {
+		panic(err)
+	}
+
+	return
 }
 
-func (missingTransaction *MissingTransaction) UnmarshalBinary(data []byte) (err error) {
+func (missingTransaction *MissingTransaction) UnmarshalObjectStorageValue(data []byte) (err error) {
 	return missingTransaction.missingSince.UnmarshalBinary(data)
 }
diff --git a/packages/binary/tangle/model/transactionmetadata/transactionmetadata.go b/packages/binary/tangle/model/transactionmetadata/transactionmetadata.go
index 1fcf1c255093cb2e9f7dec98fae7426e05ed33ec..74e222bbcdfb8face95c981dcfbd0bb75c2cd697 100644
--- a/packages/binary/tangle/model/transactionmetadata/transactionmetadata.go
+++ b/packages/binary/tangle/model/transactionmetadata/transactionmetadata.go
@@ -28,11 +28,11 @@ func New(transactionId message.Id) *TransactionMetadata {
 	}
 }
 
-func FromStorage(id []byte) objectstorage.StorableObject {
+func StorableObjectFromKey(id []byte) (objectstorage.StorableObject, error) {
 	result := &TransactionMetadata{}
 	copy(result.transactionId[:], id)
 
-	return result
+	return result, nil
 }
 
 func (transactionMetadata *TransactionMetadata) IsSolid() (result bool) {
@@ -77,7 +77,7 @@ func (transactionMetadata *TransactionMetadata) GetSoldificationTime() time.Time
 	return transactionMetadata.solidificationTime
 }
 
-func (transactionMetadata *TransactionMetadata) GetStorageKey() []byte {
+func (transactionMetadata *TransactionMetadata) ObjectStorageKey() []byte {
 	return transactionMetadata.transactionId[:]
 }
 
@@ -85,15 +85,15 @@ func (transactionMetadata *TransactionMetadata) Update(other objectstorage.Stora
 
 }
 
-func (transactionMetadata *TransactionMetadata) MarshalBinary() ([]byte, error) {
+func (transactionMetadata *TransactionMetadata) ObjectStorageValue() []byte {
 	return (&Proto{
 		receivedTime:       transactionMetadata.receivedTime,
 		solidificationTime: transactionMetadata.solidificationTime,
 		solid:              transactionMetadata.solid,
-	}).ToBytes(), nil
+	}).ToBytes()
 }
 
-func (transactionMetadata *TransactionMetadata) UnmarshalBinary(data []byte) (err error) {
+func (transactionMetadata *TransactionMetadata) UnmarshalObjectStorageValue(data []byte) (err error) {
 	proto, err := ProtoFromBytes(data)
 	if err != nil {
 		return
@@ -105,3 +105,5 @@ func (transactionMetadata *TransactionMetadata) UnmarshalBinary(data []byte) (er
 
 	return
 }
+
+var _ objectstorage.StorableObject = &TransactionMetadata{}
diff --git a/packages/binary/tangle/tangle.go b/packages/binary/tangle/tangle.go
index ac2418daf5b7619ff920a2029a840f01af177b67..3ed82777a4e82e9e070c53185f5de4b853b9e59f 100644
--- a/packages/binary/tangle/tangle.go
+++ b/packages/binary/tangle/tangle.go
@@ -41,10 +41,10 @@ type Tangle struct {
 func New(badgerInstance *badger.DB, storageId []byte) (result *Tangle) {
 	result = &Tangle{
 		storageId:                  storageId,
-		transactionStorage:         objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleTransaction...), message.FromStorage, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
-		transactionMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleTransactionMetadata...), transactionmetadata.FromStorage, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
-		approverStorage:            objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleApprovers...), approver.FromStorage, objectstorage.CacheTime(10*time.Second), objectstorage.PartitionKey(message.IdLength, message.IdLength), objectstorage.LeakDetectionEnabled(false)),
-		missingTransactionsStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleMissingTransaction...), missingtransaction.FromStorage, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
+		transactionStorage:         objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleTransaction...), message.StorableObjectFromKey, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
+		transactionMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleTransactionMetadata...), transactionmetadata.StorableObjectFromKey, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
+		approverStorage:            objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleApprovers...), approver.StorableObjectFromKey, objectstorage.CacheTime(10*time.Second), objectstorage.PartitionKey(message.IdLength, message.IdLength), objectstorage.LeakDetectionEnabled(false)),
+		missingTransactionsStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleMissingTransaction...), missingtransaction.StorableObjectFromKey, objectstorage.CacheTime(10*time.Second), objectstorage.LeakDetectionEnabled(false)),
 
 		Events: *newEvents(),
 	}
diff --git a/packages/binary/valuetransfer/payload/payload.go b/packages/binary/valuetransfer/payload/payload.go
index c97b2f128cc97537eedb61568b56f4a4ce1e3596..b24dc1ee0c631705f516b80b7b9fe4b03a97ea26 100644
--- a/packages/binary/valuetransfer/payload/payload.go
+++ b/packages/binary/valuetransfer/payload/payload.go
@@ -34,15 +34,15 @@ func New(trunkPayloadId, branchPayloadId Id, valueTransfer *transaction.Transact
 	}
 }
 
-func FromStorage(key []byte) objectstorage.StorableObject {
+func StorableObjectFromKey(key []byte) (objectstorage.StorableObject, error) {
 	id, err, _ := IdFromBytes(key)
 	if err != nil {
-		panic(err)
+		return nil, err
 	}
 
 	return &Payload{
 		id: &id,
-	}
+	}, nil
 }
 
 // FromBytes parses the marshaled version of a Payload into an object.
@@ -168,10 +168,7 @@ func (payload *Payload) Bytes() (bytes []byte) {
 	}
 
 	// retrieve bytes of transfer
-	transferBytes, err := payload.Transaction().MarshalBinary()
-	if err != nil {
-		return
-	}
+	transferBytes := payload.Transaction().ObjectStorageValue()
 
 	// marshal fields
 	payloadLength := IdLength + IdLength + len(transferBytes)
@@ -202,15 +199,21 @@ func (payload *Payload) String() string {
 
 var Type = payload.Type(1)
 
-func (payload *Payload) GetType() payload.Type {
+func (payload *Payload) Type() payload.Type {
 	return Type
 }
 
-func (payload *Payload) MarshalBinary() (bytes []byte, err error) {
-	return payload.Bytes(), nil
+func (payload *Payload) ObjectStorageValue() []byte {
+	return payload.Bytes()
+}
+
+func (payload *Payload) UnmarshalObjectStorageValue(data []byte) (err error) {
+	_, err, _ = FromBytes(data, payload)
+
+	return
 }
 
-func (payload *Payload) UnmarshalBinary(data []byte) (err error) {
+func (payload *Payload) Unmarshal(data []byte) (err error) {
 	_, err, _ = FromBytes(data, payload)
 
 	return
@@ -219,7 +222,7 @@ func (payload *Payload) UnmarshalBinary(data []byte) (err error) {
 func init() {
 	payload.RegisterType(Type, func(data []byte) (payload payload.Payload, err error) {
 		payload = &Payload{}
-		err = payload.UnmarshalBinary(data)
+		err = payload.Unmarshal(data)
 
 		return
 	})
@@ -232,11 +235,11 @@ var _ payload.Payload = &Payload{}
 
 // region StorableObject implementation ////////////////////////////////////////////////////////////////////////////////
 
-// MarshalBinary() (bytes []byte, err error) already implemented by Payload
+// ObjectStorageValue() (bytes []byte, err error) already implemented by Payload
 
-// UnmarshalBinary(data []byte) (err error) already implemented by Payload
+// UnmarshalObjectStorageValue(data []byte) (err error) already implemented by Payload
 
-func (payload *Payload) GetStorageKey() []byte {
+func (payload *Payload) ObjectStorageKey() []byte {
 	id := payload.Id()
 
 	return id[:]
diff --git a/packages/binary/valuetransfer/tangle/attachment.go b/packages/binary/valuetransfer/tangle/attachment.go
index 9dcfadb462596bd48d54d50977f88ed8faf9f2ca..122ca25ad9baf4ea24e3b1c42b1fd0628893cbf7 100644
--- a/packages/binary/valuetransfer/tangle/attachment.go
+++ b/packages/binary/valuetransfer/tangle/attachment.go
@@ -33,7 +33,7 @@ func NewAttachment(transactionId transaction.Id, payloadId payload.Id) *Attachme
 	}
 }
 
-// AttachmentFromBytes unmarshals a MissingOutput from a sequence of bytes - it either creates a new object or fills the
+// AttachmentFromBytes unmarshals an Attachment from a sequence of bytes - it either creates a new object or fills the
 // optionally provided one with the parsed information.
 func AttachmentFromBytes(bytes []byte, optionalTargetObject ...*Attachment) (result *Attachment, err error, consumedBytes int) {
 	// determine the target object that will hold the unmarshaled information
@@ -54,20 +54,30 @@ func AttachmentFromBytes(bytes []byte, optionalTargetObject ...*Attachment) (res
 	if result.payloadId, err = payload.ParseId(marshalUtil); err != nil {
 		return
 	}
+	result.storageKey = marshalutil.New(bytes[:AttachmentLength]).Bytes(true)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// AttachmentFromStorage gets called when we restore an Attachment from the storage - it parses the key bytes and
+// Parse is a wrapper for simplified unmarshaling of Attachments from a byte stream using the marshalUtil package.
+func ParseAttachment(marshalUtil *marshalutil.MarshalUtil) (*Attachment, error) {
+	if attachment, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return AttachmentFromBytes(data) }); err != nil {
+		return nil, err
+	} else {
+		return attachment.(*Attachment), nil
+	}
+}
+
+// AttachmentFromStorageKey gets called when we restore an Attachment from the storage - it parses the key bytes and
 // returns the new object.
-func AttachmentFromStorage(keyBytes []byte) objectstorage.StorableObject {
+func AttachmentFromStorageKey(keyBytes []byte) (objectstorage.StorableObject, error) {
 	result, err, _ := AttachmentFromBytes(keyBytes)
 	if err != nil {
-		panic(err)
+		return nil, err
 	}
 
-	return result
+	return result, nil
 }
 
 // TransactionId returns the transaction id of this Attachment.
@@ -80,9 +90,9 @@ func (attachment *Attachment) PayloadId() payload.Id {
 	return attachment.payloadId
 }
 
-// Bytes marshals an Attachment into a sequence of bytes.
+// Bytes marshals the Attachment into a sequence of bytes.
 func (attachment *Attachment) Bytes() []byte {
-	return attachment.GetStorageKey()
+	return attachment.ObjectStorageKey()
 }
 
 // String returns a human readable version of the Attachment.
@@ -93,20 +103,20 @@ func (attachment *Attachment) String() string {
 	)
 }
 
-// GetStorageKey returns the key that is used to store the object in the database.
-func (attachment *Attachment) GetStorageKey() []byte {
+// ObjectStorageKey returns the key that is used to store the object in the database.
+func (attachment *Attachment) ObjectStorageKey() []byte {
 	return attachment.storageKey
 }
 
-// MarshalBinary marshals the "content part" of an Attachment to a sequence of bytes. Since all of the information for
-// this object are stored in its key, this method does nothing and is only required to conform with the interface.
-func (attachment *Attachment) MarshalBinary() (data []byte, err error) {
+// ObjectStorageValue marshals the "content part" of an Attachment to a sequence of bytes. Since all of the information
+// for this object are stored in its key, this method does nothing and is only required to conform with the interface.
+func (attachment *Attachment) ObjectStorageValue() (data []byte) {
 	return
 }
 
-// UnmarshalBinary unmarshals the "content part" of an Attachment from a sequence of bytes. Since all of the information
+// UnmarshalObjectStorageValue unmarshals the "content part" of an Attachment from a sequence of bytes. Since all of the information
 // for this object are stored in its key, this method does nothing and is only required to conform with the interface.
-func (attachment *Attachment) UnmarshalBinary(data []byte) (err error) {
+func (attachment *Attachment) UnmarshalObjectStorageValue(data []byte) (err error) {
 	return
 }
 
diff --git a/packages/binary/valuetransfer/tangle/consumer.go b/packages/binary/valuetransfer/tangle/consumer.go
new file mode 100644
index 0000000000000000000000000000000000000000..e03cd0a25308689daa3748ccf8c04c408a9a3186
--- /dev/null
+++ b/packages/binary/valuetransfer/tangle/consumer.go
@@ -0,0 +1,131 @@
+package tangle
+
+import (
+	"github.com/iotaledger/hive.go/objectstorage"
+	"github.com/iotaledger/hive.go/stringify"
+
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/transaction"
+)
+
+// Consumer stores the information which transaction output was consumed by which transaction. We need this to be able
+// to perform reverse lookups from transaction outputs to their corresponding consuming transactions.
+type Consumer struct {
+	objectstorage.StorableObjectFlags
+
+	consumedInput transaction.OutputId
+	transactionId transaction.Id
+
+	storageKey []byte
+}
+
+// NewConsumer creates a Consumer object with the given information.
+func NewConsumer(consumedInput transaction.OutputId, transactionId transaction.Id) *Consumer {
+	return &Consumer{
+		consumedInput: consumedInput,
+		transactionId: transactionId,
+
+		storageKey: marshalutil.New(ConsumerLength).
+			WriteBytes(consumedInput.Bytes()).
+			WriteBytes(transactionId.Bytes()).
+			Bytes(),
+	}
+}
+
+// ConsumerFromBytes unmarshals a Consumer from a sequence of bytes - it either creates a new object or fills the
+// optionally provided one with the parsed information.
+func ConsumerFromBytes(bytes []byte, optionalTargetObject ...*Consumer) (result *Consumer, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &Consumer{}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to ConsumerFromBytes")
+	}
+
+	// parse the bytes
+	marshalUtil := marshalutil.New(bytes)
+	if result.consumedInput, err = transaction.ParseOutputId(marshalUtil); err != nil {
+		return
+	}
+	if result.transactionId, err = transaction.ParseId(marshalUtil); err != nil {
+		return
+	}
+	result.storageKey = marshalutil.New(bytes[:ConsumerLength]).Bytes(true)
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+// Parse is a wrapper for simplified unmarshaling of Consumers from a byte stream using the marshalUtil package.
+func ParseConsumer(marshalUtil *marshalutil.MarshalUtil) (*Consumer, error) {
+	if consumer, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return ConsumerFromBytes(data) }); err != nil {
+		return nil, err
+	} else {
+		return consumer.(*Consumer), nil
+	}
+}
+
+// ConsumerFromStorage gets called when we restore an Consumer from the storage - it parses the key bytes and
+// returns the new object.
+func ConsumerFromStorage(keyBytes []byte) objectstorage.StorableObject {
+	result, err, _ := ConsumerFromBytes(keyBytes)
+	if err != nil {
+		panic(err)
+	}
+
+	return result
+}
+
+// ConsumedInput returns the OutputId of the Consumer.
+func (consumer *Consumer) ConsumedInput() transaction.OutputId {
+	return consumer.consumedInput
+}
+
+// TransactionId returns the transaction Id of this Consumer.
+func (consumer *Consumer) TransactionId() transaction.Id {
+	return consumer.transactionId
+}
+
+// Bytes marshals the Consumer into a sequence of bytes.
+func (consumer *Consumer) Bytes() []byte {
+	return consumer.ObjectStorageKey()
+}
+
+// String returns a human readable version of the Consumer.
+func (consumer *Consumer) String() string {
+	return stringify.Struct("Consumer",
+		stringify.StructField("consumedInput", consumer.ConsumedInput()),
+		stringify.StructField("transactionId", consumer.TransactionId()),
+	)
+}
+
+// ObjectStorageKey returns the key that is used to store the object in the database.
+func (consumer *Consumer) ObjectStorageKey() []byte {
+	return consumer.storageKey
+}
+
+// ObjectStorageValue marshals the "content part" of an Consumer to a sequence of bytes. Since all of the information for
+// this object are stored in its key, this method does nothing and is only required to conform with the interface.
+func (consumer *Consumer) ObjectStorageValue() (data []byte) {
+	return
+}
+
+// UnmarshalObjectStorageValue unmarshals the "content part" of a Consumer from a sequence of bytes. Since all of the information
+// for this object are stored in its key, this method does nothing and is only required to conform with the interface.
+func (consumer *Consumer) UnmarshalObjectStorageValue(data []byte) (err error) {
+	return
+}
+
+// Update is disabled - updates are supposed to happen through the setters (if existing).
+func (consumer *Consumer) Update(other objectstorage.StorableObject) {
+	panic("update forbidden")
+}
+
+// Interface contract: make compiler warn if the interface is not implemented correctly.
+var _ objectstorage.StorableObject = &Consumer{}
+
+// ConsumerLength holds the length of a marshaled Consumer in bytes.
+const ConsumerLength = transaction.OutputIdLength + transaction.IdLength
diff --git a/packages/binary/valuetransfer/tangle/events.go b/packages/binary/valuetransfer/tangle/events.go
index 15e31ddd8348f6af855e3d711fd1a924e46c2797..f36280cb9dca449d2b6ad47163741d60064ad766 100644
--- a/packages/binary/valuetransfer/tangle/events.go
+++ b/packages/binary/valuetransfer/tangle/events.go
@@ -16,6 +16,8 @@ type Events struct {
 	PayloadUnsolidifiable  *events.Event
 	TransactionRemoved     *events.Event
 	OutputMissing          *events.Event
+
+	TransactionSolid *events.Event
 }
 
 func newEvents() *Events {
@@ -25,8 +27,9 @@ func newEvents() *Events {
 		MissingPayloadReceived: events.NewEvent(cachedPayloadEvent),
 		PayloadMissing:         events.NewEvent(payloadIdEvent),
 		PayloadUnsolidifiable:  events.NewEvent(payloadIdEvent),
-		TransactionRemoved:     events.NewEvent(payloadIdEvent),
 		OutputMissing:          events.NewEvent(outputIdEvent),
+
+		TransactionSolid: events.NewEvent(transactionEvent),
 	}
 }
 
@@ -41,6 +44,13 @@ func cachedPayloadEvent(handler interface{}, params ...interface{}) {
 	)
 }
 
+func transactionEvent(handler interface{}, params ...interface{}) {
+	handler.(func(*transaction.Transaction, *CachedTransactionMetadata))(
+		params[0].(*transaction.Transaction),
+		params[1].(*CachedTransactionMetadata).Retain(),
+	)
+}
+
 func outputIdEvent(handler interface{}, params ...interface{}) {
 	handler.(func(transaction.OutputId))(params[0].(transaction.OutputId))
 }
diff --git a/packages/binary/valuetransfer/tangle/missingoutput.go b/packages/binary/valuetransfer/tangle/missingoutput.go
index 92b34c383995a0127d5b19f2775630102f4d4633..f576aed6c0edad773fd3d0b94b28313bcd511462 100644
--- a/packages/binary/valuetransfer/tangle/missingoutput.go
+++ b/packages/binary/valuetransfer/tangle/missingoutput.go
@@ -51,9 +51,9 @@ func MissingOutputFromBytes(bytes []byte, optionalTargetObject ...*MissingOutput
 	return
 }
 
-// MissingOutputFromStorage gets called when we restore a MissingOutput from the storage. The content will be
-// unmarshaled by an external caller using the binary.MarshalBinary interface.
-func MissingOutputFromStorage(keyBytes []byte) objectstorage.StorableObject {
+// MissingOutputFromStorageKey gets called when we restore a MissingOutput from the storage. The content will be
+// unmarshaled by an external caller using the binary.ObjectStorageValue interface.
+func MissingOutputFromStorageKey(keyBytes []byte) (objectstorage.StorableObject, error) {
 	outputId, err, _ := transaction.OutputIdFromBytes(keyBytes)
 	if err != nil {
 		panic(err)
@@ -61,7 +61,7 @@ func MissingOutputFromStorage(keyBytes []byte) objectstorage.StorableObject {
 
 	return &MissingOutput{
 		outputId: outputId,
-	}
+	}, nil
 }
 
 // Id returns the id of the Output that is missing.
@@ -84,26 +84,29 @@ func (missingOutput *MissingOutput) Bytes() []byte {
 	return marshalUtil.Bytes()
 }
 
-// GetStorageKey returns the key that is used to store the object in the object storage.
-func (missingOutput *MissingOutput) GetStorageKey() []byte {
+// ObjectStorageKey returns the key that is used to store the object in the object storage.
+func (missingOutput *MissingOutput) ObjectStorageKey() []byte {
 	return missingOutput.outputId.Bytes()
 }
 
-// Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
-func (missingOutput *MissingOutput) Update(other objectstorage.StorableObject) {
-	panic("implement me")
-}
-
-// MarshalBinary returns a bytes representation of the Transaction by implementing the encoding.BinaryMarshaler
+// ObjectStorageValue returns a bytes representation of the Transaction by implementing the encoding.BinaryMarshaler
 // interface.
-func (missingOutput *MissingOutput) MarshalBinary() (data []byte, err error) {
-	return missingOutput.Bytes(), nil
+func (missingOutput *MissingOutput) ObjectStorageValue() []byte {
+	return missingOutput.Bytes()
 }
 
-// UnmarshalBinary restores the values of a MissingOutput from a sequence of bytes using the  encoding.BinaryUnmarshaler
+// UnmarshalObjectStorageValue restores the values of a MissingOutput from a sequence of bytes using the  encoding.BinaryUnmarshaler
 // interface.
-func (missingOutput *MissingOutput) UnmarshalBinary(data []byte) (err error) {
+func (missingOutput *MissingOutput) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = MissingOutputFromBytes(data, missingOutput)
 
 	return
 }
+
+// Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
+func (missingOutput *MissingOutput) Update(other objectstorage.StorableObject) {
+	panic("implement me")
+}
+
+// Interface contract: make compiler warn if the interface is not implemented correctly.
+var _ objectstorage.StorableObject = &MissingOutput{}
diff --git a/packages/binary/valuetransfer/tangle/missingpayload.go b/packages/binary/valuetransfer/tangle/missingpayload.go
index c4eb653276ad39e4697adfca578e3d73a6d97496..2284ff9ab2cbe72e337afb459e82e877e9d0c5ec 100644
--- a/packages/binary/valuetransfer/tangle/missingpayload.go
+++ b/packages/binary/valuetransfer/tangle/missingpayload.go
@@ -52,10 +52,10 @@ func MissingPayloadFromBytes(bytes []byte, optionalTargetObject ...*MissingPaylo
 	return
 }
 
-// MissingPayloadFromStorage gets called when we restore an entry for a missing value transfer payload from the storage. The bytes and
-// the content will be unmarshaled by an external caller using the binary.MarshalBinary interface.
-func MissingPayloadFromStorage([]byte) objectstorage.StorableObject {
-	return &MissingPayload{}
+// MissingPayloadFromStorageKey gets called when we restore an entry for a missing value transfer payload from the storage. The bytes and
+// the content will be unmarshaled by an external caller using the binary.ObjectStorageValue interface.
+func MissingPayloadFromStorageKey([]byte) (objectstorage.StorableObject, error) {
+	return &MissingPayload{}, nil
 }
 
 // GetId returns the payload id, that is missing.
@@ -78,26 +78,29 @@ func (missingPayload *MissingPayload) Bytes() []byte {
 	return marshalUtil.Bytes()
 }
 
-// GetStorageKey returns the key that is used to store the object in the database.
-// It is required to match StorableObject interface.
-func (missingPayload *MissingPayload) GetStorageKey() []byte {
-	return missingPayload.payloadId.Bytes()
-}
-
 // Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
 // It is required to match StorableObject interface.
 func (missingPayload *MissingPayload) Update(other objectstorage.StorableObject) {
 	panic("implement me")
 }
 
-// MarshalBinary is required to match the encoding.BinaryMarshaler interface.
-func (missingPayload *MissingPayload) MarshalBinary() (data []byte, err error) {
-	return missingPayload.Bytes(), nil
+// ObjectStorageKey returns the key that is used to store the object in the database.
+// It is required to match StorableObject interface.
+func (missingPayload *MissingPayload) ObjectStorageKey() []byte {
+	return missingPayload.payloadId.Bytes()
+}
+
+// ObjectStorageValue is required to match the encoding.BinaryMarshaler interface.
+func (missingPayload *MissingPayload) ObjectStorageValue() (data []byte) {
+	return missingPayload.Bytes()
 }
 
-// UnmarshalBinary is required to match the encoding.BinaryUnmarshaler interface.
-func (missingPayload *MissingPayload) UnmarshalBinary(data []byte) (err error) {
+// UnmarshalObjectStorageValue is required to match the encoding.BinaryUnmarshaler interface.
+func (missingPayload *MissingPayload) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = MissingPayloadFromBytes(data, missingPayload)
 
 	return
 }
+
+// Interface contract: make compiler warn if the interface is not implemented correctly.
+var _ objectstorage.StorableObject = &MissingPayload{}
diff --git a/packages/binary/valuetransfer/tangle/payloadapprover.go b/packages/binary/valuetransfer/tangle/payloadapprover.go
index e86379258ed67159df15b2e40d10313d5b2ec9a4..d54930fb05d6e48948e860c1520493f98bd125a9 100644
--- a/packages/binary/valuetransfer/tangle/payloadapprover.go
+++ b/packages/binary/valuetransfer/tangle/payloadapprover.go
@@ -31,19 +31,19 @@ func NewPayloadApprover(referencedPayload payload.Id, approvingPayload payload.I
 	}
 }
 
-// PayloadApproverFromStorage get's called when we restore transaction metadata from the storage.
-// In contrast to other database models, it unmarshals the information from the key and does not use the UnmarshalBinary
+// PayloadApproverFromStorageKey get's called when we restore transaction metadata from the storage.
+// In contrast to other database models, it unmarshals the information from the key and does not use the UnmarshalObjectStorageValue
 // method.
-func PayloadApproverFromStorage(idBytes []byte) objectstorage.StorableObject {
+func PayloadApproverFromStorageKey(idBytes []byte) (objectstorage.StorableObject, error) {
 	marshalUtil := marshalutil.New(idBytes)
 
 	referencedPayloadId, err := payload.ParseId(marshalUtil)
 	if err != nil {
-		panic(err)
+		return nil, err
 	}
 	approvingPayloadId, err := payload.ParseId(marshalUtil)
 	if err != nil {
-		panic(err)
+		return nil, err
 	}
 
 	result := &PayloadApprover{
@@ -52,7 +52,7 @@ func PayloadApproverFromStorage(idBytes []byte) objectstorage.StorableObject {
 		storageKey:          marshalUtil.Bytes(true),
 	}
 
-	return result
+	return result, nil
 }
 
 // GetApprovingPayloadId returns the id of the approving payload.
@@ -60,21 +60,21 @@ func (payloadApprover *PayloadApprover) GetApprovingPayloadId() payload.Id {
 	return payloadApprover.approvingPayloadId
 }
 
-// GetStorageKey returns the key that is used to store the object in the database.
+// ObjectStorageKey returns the key that is used to store the object in the database.
 // It is required to match StorableObject interface.
-func (payloadApprover *PayloadApprover) GetStorageKey() []byte {
+func (payloadApprover *PayloadApprover) ObjectStorageKey() []byte {
 	return payloadApprover.storageKey
 }
 
-// MarshalBinary is implemented to conform with the StorableObject interface, but it does not really do anything,
+// ObjectStorageValue is implemented to conform with the StorableObject interface, but it does not really do anything,
 // since all of the information about an approver are stored in the "key".
-func (payloadApprover *PayloadApprover) MarshalBinary() (data []byte, err error) {
+func (payloadApprover *PayloadApprover) ObjectStorageValue() (data []byte) {
 	return
 }
 
-// UnmarshalBinary is implemented to conform with the StorableObject interface, but it does not really do anything,
-// since all of the information about an approver are stored in the "key".
-func (payloadApprover *PayloadApprover) UnmarshalBinary(data []byte) error {
+// UnmarshalObjectStorageValue is implemented to conform with the StorableObject interface, but it does not really do
+// anything, since all of the information about an approver are stored in the "key".
+func (payloadApprover *PayloadApprover) UnmarshalObjectStorageValue(data []byte) error {
 	return nil
 }
 
diff --git a/packages/binary/valuetransfer/tangle/payloadmetadata.go b/packages/binary/valuetransfer/tangle/payloadmetadata.go
index d693c86ef09f99f746aff937840be6c690709219..e17eb3f042104a04506a7455d46c25b6447efac5 100644
--- a/packages/binary/valuetransfer/tangle/payloadmetadata.go
+++ b/packages/binary/valuetransfer/tangle/payloadmetadata.go
@@ -60,17 +60,17 @@ func PayloadMetadataFromBytes(bytes []byte, optionalTargetObject ...*PayloadMeta
 	return
 }
 
-// PayloadMetadataFromStorage gets called when we restore transaction metadata from the storage. The bytes and the content will be
-// unmarshaled by an external caller using the binary.MarshalBinary interface.
-func PayloadMetadataFromStorage(id []byte) objectstorage.StorableObject {
+// PayloadMetadataFromStorageKey gets called when we restore transaction metadata from the storage. The bytes and the content will be
+// unmarshaled by an external caller using the binary.ObjectStorageValue interface.
+func PayloadMetadataFromStorageKey(id []byte) (objectstorage.StorableObject, error) {
 	result := &PayloadMetadata{}
 
 	var err error
 	if result.payloadId, err = payload.ParseId(marshalutil.New(id)); err != nil {
-		panic(err)
+		return nil, err
 	}
 
-	return result
+	return result, nil
 }
 
 // ParsePayloadMetadata is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
@@ -153,9 +153,9 @@ func (payloadMetadata *PayloadMetadata) String() string {
 	)
 }
 
-// GetStorageKey returns the key that is used to store the object in the database.
+// ObjectStorageKey returns the key that is used to store the object in the database.
 // It is required to match StorableObject interface.
-func (payloadMetadata *PayloadMetadata) GetStorageKey() []byte {
+func (payloadMetadata *PayloadMetadata) ObjectStorageKey() []byte {
 	return payloadMetadata.payloadId.Bytes()
 }
 
@@ -165,13 +165,13 @@ func (payloadMetadata *PayloadMetadata) Update(other objectstorage.StorableObjec
 	panic("update forbidden")
 }
 
-// MarshalBinary is required to match the encoding.BinaryMarshaler interface.
-func (payloadMetadata *PayloadMetadata) MarshalBinary() ([]byte, error) {
-	return payloadMetadata.Bytes(), nil
+// ObjectStorageValue is required to match the encoding.BinaryMarshaler interface.
+func (payloadMetadata *PayloadMetadata) ObjectStorageValue() []byte {
+	return payloadMetadata.Bytes()
 }
 
-// UnmarshalBinary is required to match the encoding.BinaryUnmarshaler interface.
-func (payloadMetadata *PayloadMetadata) UnmarshalBinary(data []byte) (err error) {
+// UnmarshalObjectStorageValue is required to match the encoding.BinaryUnmarshaler interface.
+func (payloadMetadata *PayloadMetadata) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = PayloadMetadataFromBytes(data, payloadMetadata)
 
 	return
diff --git a/packages/binary/valuetransfer/tangle/tangle.go b/packages/binary/valuetransfer/tangle/tangle.go
index 5c61b2b713d39b43e8e6d1b9de471e3bcd7de928..bea66a480481a8ac931c68b0c4b2e58b9de15274 100644
--- a/packages/binary/valuetransfer/tangle/tangle.go
+++ b/packages/binary/valuetransfer/tangle/tangle.go
@@ -2,7 +2,6 @@ package tangle
 
 import (
 	"container/list"
-	"fmt"
 	"time"
 
 	"github.com/dgraph-io/badger/v2"
@@ -23,7 +22,9 @@ type Tangle struct {
 	payloadMetadataStorage *objectstorage.ObjectStorage
 	approverStorage        *objectstorage.ObjectStorage
 	missingPayloadStorage  *objectstorage.ObjectStorage
+	attachmentStorage      *objectstorage.ObjectStorage
 
+	consumerStorage                  *objectstorage.ObjectStorage
 	transactionOutputMetadataStorage *objectstorage.ObjectStorage
 	missingOutputStorage             *objectstorage.ObjectStorage
 
@@ -38,13 +39,20 @@ func New(badgerInstance *badger.DB, storageId []byte) (result *Tangle) {
 	result = &Tangle{
 		storageId: storageId,
 
-		payloadStorage:         objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferPayload...), payload.FromStorage, objectstorage.CacheTime(time.Second)),
-		payloadMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferPayloadMetadata...), PayloadMetadataFromStorage, objectstorage.CacheTime(time.Second)),
-		approverStorage:        objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferApprover...), PayloadApproverFromStorage, objectstorage.CacheTime(time.Second), objectstorage.PartitionKey(payload.IdLength, payload.IdLength), objectstorage.KeysOnly(true)),
-		missingPayloadStorage:  objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferMissingPayload...), MissingPayloadFromStorage, objectstorage.CacheTime(time.Second)),
+		// payload related storage
+		payloadStorage:         objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferPayload...), payload.StorableObjectFromKey, objectstorage.CacheTime(time.Second)),
+		payloadMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferPayloadMetadata...), PayloadMetadataFromStorageKey, objectstorage.CacheTime(time.Second)),
+		missingPayloadStorage:  objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferMissingPayload...), MissingPayloadFromStorageKey, objectstorage.CacheTime(time.Second)),
+		approverStorage:        objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferApprover...), PayloadApproverFromStorageKey, objectstorage.CacheTime(time.Second), objectstorage.PartitionKey(payload.IdLength, payload.IdLength), objectstorage.KeysOnly(true)),
 
-		transactionOutputMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleApprovers...), transaction.OutputFromStorage, objectstorage.CacheTime(time.Second)),
-		missingOutputStorage:             objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferMissingPayload...), MissingOutputFromStorage, objectstorage.CacheTime(time.Second)),
+		// transaction related storage
+		transactionOutputMetadataStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.TangleApprovers...), transaction.OutputFromStorageKey, objectstorage.CacheTime(time.Second)),
+		missingOutputStorage:             objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferMissingPayload...), MissingOutputFromStorageKey, objectstorage.CacheTime(time.Second)),
+		consumerStorage:                  objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferConsumer...), transaction.OutputFromStorageKey, objectstorage.CacheTime(time.Second)),
+
+		attachmentStorage: objectstorage.New(badgerInstance, append(storageId, storageprefix.ValueTransferAttachment...), AttachmentFromStorageKey, objectstorage.CacheTime(time.Second)),
+
+		// transaction related storage
 
 		Events: *newEvents(),
 	}
@@ -67,6 +75,11 @@ func (tangle *Tangle) GetPayloadMetadata(payloadId payload.Id) *CachedPayloadMet
 	return &CachedPayloadMetadata{CachedObject: tangle.payloadMetadataStorage.Load(payloadId.Bytes())}
 }
 
+// GetPayloadMetadata retrieves the metadata of a value payload from the object storage.
+func (tangle *Tangle) GetTransactionMetadata(transactionId transaction.Id) *CachedTransactionMetadata {
+	return &CachedTransactionMetadata{CachedObject: tangle.missingOutputStorage.Load(transactionId.Bytes())}
+}
+
 // GetApprovers retrieves the approvers of a payload from the object storage.
 func (tangle *Tangle) GetApprovers(transactionId payload.Id) CachedApprovers {
 	approvers := make(CachedApprovers, 0)
@@ -123,21 +136,6 @@ func (tangle *Tangle) storePayloadWorker(payloadToStore *payload.Payload) {
 	payloadId := payloadToStore.Id()
 	cachedMetadata := &CachedPayloadMetadata{CachedObject: tangle.payloadMetadataStorage.Store(NewPayloadMetadata(payloadId))}
 
-	// store trunk approver
-	trunkId := payloadToStore.TrunkId()
-	tangle.approverStorage.Store(NewPayloadApprover(trunkId, payloadId)).Release()
-
-	// store branch approver
-	if branchId := payloadToStore.BranchId(); branchId != trunkId {
-		tangle.approverStorage.Store(NewPayloadApprover(branchId, trunkId)).Release()
-	}
-
-	// trigger events
-	if tangle.missingPayloadStorage.DeleteIfPresent(payloadId.Bytes()) {
-		tangle.Events.MissingPayloadReceived.Trigger(cachedPayload, cachedMetadata)
-	}
-	tangle.Events.PayloadAttached.Trigger(cachedPayload, cachedMetadata)
-
 	// retrieve or store TransactionMetadata
 	newTransaction := false
 	transactionId := cachedPayload.Unwrap().Transaction().Id()
@@ -151,11 +149,33 @@ func (tangle *Tangle) storePayloadWorker(payloadToStore *payload.Payload) {
 		return result
 	})}
 
-	// if the transaction is new, store the Consumers.
+	// store trunk approver
+	trunkId := payloadToStore.TrunkId()
+	tangle.approverStorage.Store(NewPayloadApprover(trunkId, payloadId)).Release()
+
+	// store branch approver
+	if branchId := payloadToStore.BranchId(); branchId != trunkId {
+		tangle.approverStorage.Store(NewPayloadApprover(branchId, trunkId)).Release()
+	}
+
+	// store the consumers, the first time we see a Transaction
 	if newTransaction {
-		fmt.Println("git aWADD")
+		payloadToStore.Transaction().Inputs().ForEach(func(outputId transaction.OutputId) bool {
+			tangle.consumerStorage.Store(NewConsumer(outputId, transactionId))
+
+			return true
+		})
 	}
 
+	// store attachment
+	tangle.attachmentStorage.StoreIfAbsent(NewAttachment(payloadToStore.Transaction().Id(), payloadToStore.Id()))
+
+	// trigger events
+	if tangle.missingPayloadStorage.DeleteIfPresent(payloadId.Bytes()) {
+		tangle.Events.MissingPayloadReceived.Trigger(cachedPayload, cachedMetadata)
+	}
+	tangle.Events.PayloadAttached.Trigger(cachedPayload, cachedMetadata)
+
 	// check solidity
 	tangle.solidifierWorkerPool.Submit(func() {
 		tangle.solidifyTransactionWorker(cachedPayload, cachedMetadata, cachedTransactionMetadata)
@@ -164,53 +184,73 @@ func (tangle *Tangle) storePayloadWorker(payloadToStore *payload.Payload) {
 
 // solidifyTransactionWorker is the worker function that solidifies the payloads (recursively from past to present).
 func (tangle *Tangle) solidifyTransactionWorker(cachedPayload *payload.CachedPayload, cachedMetadata *CachedPayloadMetadata, cachedTransactionMetadata *CachedTransactionMetadata) {
-	popElementsFromStack := func(stack *list.List) (*payload.CachedPayload, *CachedPayloadMetadata) {
+	popElementsFromStack := func(stack *list.List) (*payload.CachedPayload, *CachedPayloadMetadata, *CachedTransactionMetadata) {
 		currentSolidificationEntry := stack.Front()
-		currentCachedPayload := currentSolidificationEntry.Value.([2]interface{})[0]
-		currentCachedMetadata := currentSolidificationEntry.Value.([2]interface{})[1]
+		currentCachedPayload := currentSolidificationEntry.Value.([3]interface{})[0]
+		currentCachedMetadata := currentSolidificationEntry.Value.([3]interface{})[1]
+		currentCachedTransactionMetadata := currentSolidificationEntry.Value.([3]interface{})[2]
 		stack.Remove(currentSolidificationEntry)
 
-		return currentCachedPayload.(*payload.CachedPayload), currentCachedMetadata.(*CachedPayloadMetadata)
+		return currentCachedPayload.(*payload.CachedPayload), currentCachedMetadata.(*CachedPayloadMetadata), currentCachedTransactionMetadata.(*CachedTransactionMetadata)
 	}
 
 	// initialize the stack
 	solidificationStack := list.New()
-	solidificationStack.PushBack([2]interface{}{cachedPayload, cachedMetadata})
+	solidificationStack.PushBack([3]interface{}{cachedPayload, cachedMetadata, cachedTransactionMetadata})
 
 	// process payloads that are supposed to be checked for solidity recursively
 	for solidificationStack.Len() > 0 {
-		currentCachedPayload, currentCachedMetadata := popElementsFromStack(solidificationStack)
+		currentCachedPayload, currentCachedMetadata, currentCachedTransactionMetadata := popElementsFromStack(solidificationStack)
 
 		currentPayload := currentCachedPayload.Unwrap()
-		currentMetadata := currentCachedMetadata.Unwrap()
-		if currentPayload == nil || currentMetadata == nil {
+		currentPayloadMetadata := currentCachedMetadata.Unwrap()
+		currentTransaction := currentPayload.Transaction()
+		currentTransactionMetadata := currentCachedTransactionMetadata.Unwrap()
+		if currentPayload == nil || currentPayloadMetadata == nil || currentTransactionMetadata == nil {
 			currentCachedPayload.Release()
 			currentCachedMetadata.Release()
-			cachedTransactionMetadata.Release()
+			currentCachedTransactionMetadata.Release()
 
 			continue
 		}
 
-		// if current transaction is solid and was not marked as solid before: mark as solid and propagate
-		if tangle.isPayloadSolid(currentPayload, currentMetadata) && tangle.isTransactionSolid(currentPayload.Transaction(), cachedTransactionMetadata.Unwrap()) {
-			if currentMetadata.SetSolid(true) {
+		// if current transaction and payload are solid ...
+		if tangle.isPayloadSolid(currentPayload, currentPayloadMetadata) && tangle.isTransactionSolid(currentTransaction, currentTransactionMetadata) {
+			payloadBecameSolid := currentPayloadMetadata.SetSolid(true)
+			transactionBecameSolid := currentTransactionMetadata.SetSolid(true)
+
+			// if payload was marked as solid the first time ...
+			if payloadBecameSolid {
 				tangle.Events.PayloadSolid.Trigger(currentCachedPayload, currentCachedMetadata)
 
 				tangle.GetApprovers(currentPayload.Id()).Consume(func(approver *PayloadApprover) {
-					approverTransactionId := approver.GetApprovingPayloadId()
-
-					solidificationStack.PushBack([2]interface{}{
-						tangle.GetPayload(approverTransactionId),
-						tangle.GetPayloadMetadata(approverTransactionId),
+					approvingPayloadId := approver.GetApprovingPayloadId()
+					approvingCachedPayload := tangle.GetPayload(approvingPayloadId)
+
+					approvingCachedPayload.Consume(func(payload *payload.Payload) {
+						solidificationStack.PushBack([3]interface{}{
+							approvingCachedPayload,
+							tangle.GetPayloadMetadata(approvingPayloadId),
+							tangle.GetTransactionMetadata(payload.Transaction().Id()),
+						})
 					})
 				})
 			}
+
+			if transactionBecameSolid {
+				tangle.Events.TransactionSolid.Trigger(currentTransaction, currentTransactionMetadata)
+
+				currentTransaction.Inputs().ForEach(func(outputId transaction.OutputId) bool {
+					return true
+				})
+				//tangle.GetConsumers(outputId)
+			}
 		}
 
-		// release cached results
+		// release cached objects
 		currentCachedPayload.Release()
 		currentCachedMetadata.Release()
-		cachedTransactionMetadata.Release()
+		currentCachedTransactionMetadata.Release()
 	}
 }
 
diff --git a/packages/binary/valuetransfer/tangle/transactionmetadata.go b/packages/binary/valuetransfer/tangle/transactionmetadata.go
index 898c57a7002705de783894a1cd0a2b915d2c4ef8..e4c757533f18ed534618de662be621b9fbff8a4c 100644
--- a/packages/binary/valuetransfer/tangle/transactionmetadata.go
+++ b/packages/binary/valuetransfer/tangle/transactionmetadata.go
@@ -61,7 +61,7 @@ func TransactionMetadataFromBytes(bytes []byte, optionalTargetObject ...*Transac
 }
 
 // TransactionMetadataFromStorage is the factory method for TransactionMetadata objects stored in the objectstorage. The bytes and the content
-// will be filled by the objectstorage, by subsequently calling MarshalBinary.
+// will be filled by the objectstorage, by subsequently calling ObjectStorageValue.
 func TransactionMetadataFromStorage(storageKey []byte) objectstorage.StorableObject {
 	result := &TransactionMetadata{}
 
@@ -153,8 +153,8 @@ func (transactionMetadata *TransactionMetadata) String() string {
 	)
 }
 
-// GetStorageKey returns the key that is used to identify the TransactionMetadata in the objectstorage.
-func (transactionMetadata *TransactionMetadata) GetStorageKey() []byte {
+// ObjectStorageKey returns the key that is used to identify the TransactionMetadata in the objectstorage.
+func (transactionMetadata *TransactionMetadata) ObjectStorageKey() []byte {
 	return transactionMetadata.id.Bytes()
 }
 
@@ -163,15 +163,15 @@ func (transactionMetadata *TransactionMetadata) Update(other objectstorage.Stora
 	panic("update forbidden")
 }
 
-// MarshalBinary marshals the TransactionMetadata object into a sequence of bytes and matches the encoding.BinaryMarshaler
+// ObjectStorageValue marshals the TransactionMetadata object into a sequence of bytes and matches the encoding.BinaryMarshaler
 // interface.
-func (transactionMetadata *TransactionMetadata) MarshalBinary() ([]byte, error) {
-	return transactionMetadata.Bytes(), nil
+func (transactionMetadata *TransactionMetadata) ObjectStorageValue() []byte {
+	return transactionMetadata.Bytes()
 }
 
-// UnmarshalBinary restores the values of a TransactionMetadata object from a sequence of bytes and matches the
+// UnmarshalObjectStorageValue restores the values of a TransactionMetadata object from a sequence of bytes and matches the
 // encoding.BinaryUnmarshaler interface.
-func (transactionMetadata *TransactionMetadata) UnmarshalBinary(data []byte) (err error) {
+func (transactionMetadata *TransactionMetadata) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = TransactionMetadataFromBytes(data, transactionMetadata)
 
 	return
@@ -211,3 +211,6 @@ func (cachedTransactionMetadata *CachedTransactionMetadata) Unwrap() *Transactio
 		}
 	}
 }
+
+// Interface contract: make compiler warn if the interface is not implemented correctly.
+var _ objectstorage.StorableObject = &TransactionMetadata{}
diff --git a/packages/binary/valuetransfer/tangle/transactionoutputmetadata.go b/packages/binary/valuetransfer/tangle/transactionoutputmetadata.go
index 9e0c15feea79b708abdc6db89d573444d98da3ea..8d0bf541f132d07e94fc7d288febc50a2549a007 100644
--- a/packages/binary/valuetransfer/tangle/transactionoutputmetadata.go
+++ b/packages/binary/valuetransfer/tangle/transactionoutputmetadata.go
@@ -61,7 +61,7 @@ func TransactionOutputMetadataFromBytes(bytes []byte, optionalTargetObject ...*T
 }
 
 // TransactionOutputMetadataFromStorage is the factory method for TransactionOutputMetadata objects stored in the objectstorage. The bytes and the content
-// will be filled by the objectstorage, by subsequently calling MarshalBinary.
+// will be filled by the objectstorage, by subsequently calling ObjectStorageValue.
 func TransactionOutputMetadataFromStorage(storageKey []byte) objectstorage.StorableObject {
 	result := &TransactionOutputMetadata{}
 
@@ -153,30 +153,32 @@ func (transactionOutputMetadata *TransactionOutputMetadata) String() string {
 	)
 }
 
-// GetStorageKey returns the key that is used to identify the TransactionOutputMetadata in the objectstorage.
-func (transactionOutputMetadata *TransactionOutputMetadata) GetStorageKey() []byte {
+// ObjectStorageKey returns the key that is used to identify the TransactionOutputMetadata in the objectstorage.
+func (transactionOutputMetadata *TransactionOutputMetadata) ObjectStorageKey() []byte {
 	return transactionOutputMetadata.id.Bytes()
 }
 
-// Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
-func (transactionOutputMetadata *TransactionOutputMetadata) Update(other objectstorage.StorableObject) {
-	panic("update forbidden")
+// ObjectStorageValue returns the bytes, that are stored in the value part of the k/v store.
+func (transactionOutputMetadata *TransactionOutputMetadata) ObjectStorageValue() []byte {
+	return transactionOutputMetadata.Bytes()
 }
 
-// MarshalBinary marshals the TransactionOutputMetadata object into a sequence of bytes and matches the encoding.BinaryMarshaler
-// interface.
-func (transactionOutputMetadata *TransactionOutputMetadata) MarshalBinary() ([]byte, error) {
-	return transactionOutputMetadata.Bytes(), nil
-}
-
-// UnmarshalBinary restores the values of a TransactionOutputMetadata object from a sequence of bytes and matches the
+// UnmarshalObjectStorageValue restores the values of a TransactionOutputMetadata object from a sequence of bytes and matches the
 // encoding.BinaryUnmarshaler interface.
-func (transactionOutputMetadata *TransactionOutputMetadata) UnmarshalBinary(data []byte) (err error) {
+func (transactionOutputMetadata *TransactionOutputMetadata) UnmarshalObjectStorageValue(data []byte) (err error) {
 	_, err, _ = TransactionOutputMetadataFromBytes(data, transactionOutputMetadata)
 
 	return
 }
 
+// Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
+func (transactionOutputMetadata *TransactionOutputMetadata) Update(other objectstorage.StorableObject) {
+	panic("update forbidden")
+}
+
+// Interface contract: make compiler warn if the interface is not implemented correctly.
+var _ objectstorage.StorableObject = &TransactionOutputMetadata{}
+
 // CachedTransactionOutputMetadata is a wrapper for the object storage, that takes care of type casting the TransactionOutputMetadata objects.
 // Since go does not have generics (yet), the object storage works based on the generic "interface{}" type, which means
 // that we have to regularly type cast the returned objects, to match the expected type. To reduce the burden of
diff --git a/packages/binary/valuetransfer/transaction/output.go b/packages/binary/valuetransfer/transaction/output.go
index 949434dcb5c97c5749ccde643e0a0c0fb43db4a7..afc9cf4092c949adfb01643c42b09409af7def65 100644
--- a/packages/binary/valuetransfer/transaction/output.go
+++ b/packages/binary/valuetransfer/transaction/output.go
@@ -1,7 +1,7 @@
 package transaction
 
 import (
-	"fmt"
+	"time"
 
 	"github.com/iotaledger/hive.go/objectstorage"
 
@@ -14,6 +14,8 @@ import (
 type Output struct {
 	address       address.Address
 	transactionId Id
+	solid         bool
+	solidSince    time.Time
 	balances      []*balance.Balance
 
 	objectstorage.StorableObjectFlags
@@ -25,19 +27,66 @@ func NewOutput(address address.Address, transactionId Id, balances []*balance.Ba
 	return &Output{
 		address:       address,
 		transactionId: transactionId,
+		solid:         false,
+		solidSince:    time.Time{},
 		balances:      balances,
 
 		storageKey: marshalutil.New().WriteBytes(address.Bytes()).WriteBytes(transactionId.Bytes()).Bytes(),
 	}
 }
 
-// OutputFromStorage get's called when we restore a Output from the storage.
+// OutputFromBytes unmarshals an Output object from a sequence of bytes.
+// It either creates a new object or fills the optionally provided object with the parsed information.
+func OutputFromBytes(bytes []byte, optionalTargetObject ...*Output) (result *Output, err error, consumedBytes int) {
+	// determine the target object that will hold the unmarshaled information
+	switch len(optionalTargetObject) {
+	case 0:
+		result = &Output{}
+	case 1:
+		result = optionalTargetObject[0]
+	default:
+		panic("too many arguments in call to OutputFromBytes")
+	}
+
+	// parse the bytes
+	marshalUtil := marshalutil.New(bytes)
+	if result.address, err = address.Parse(marshalUtil); err != nil {
+		return
+	}
+	if result.transactionId, err = ParseId(marshalUtil); err != nil {
+		return
+	}
+	if result.solid, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.solidSince, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	var balanceCount uint32
+	if balanceCount, err = marshalUtil.ReadUint32(); err != nil {
+		return
+	} else {
+		result.balances = make([]*balance.Balance, balanceCount)
+		for i := uint32(0); i < balanceCount; i++ {
+			result.balances[i], err = balance.Parse(marshalUtil)
+			if err != nil {
+				return
+			}
+		}
+	}
+	result.storageKey = marshalutil.New().WriteBytes(result.address.Bytes()).WriteBytes(result.transactionId.Bytes()).Bytes()
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+// OutputFromStorageKey get's called when we restore a Output from the storage.
 // In contrast to other database models, it unmarshals some information from the key so we simply store the key before
-// it gets handed over to UnmarshalBinary (by the ObjectStorage).
-func OutputFromStorage(keyBytes []byte) objectstorage.StorableObject {
+// it gets handed over to UnmarshalObjectStorageValue (by the ObjectStorage).
+func OutputFromStorageKey(keyBytes []byte) (objectstorage.StorableObject, error) {
 	return &Output{
-		storageKey: marshalutil.New(keyBytes).Bytes(true),
-	}
+		storageKey: keyBytes[:OutputIdLength],
+	}, nil
 }
 
 // Address returns the address that this output belongs to.
@@ -55,9 +104,9 @@ func (output *Output) Balances() []*balance.Balance {
 	return output.balances
 }
 
-// MarshalBinary marshals the balances into a sequence of bytes - the address and transaction id are stored inside the key
+// ObjectStorageValue marshals the balances into a sequence of bytes - the address and transaction id are stored inside the key
 // and are ignored here.
-func (output *Output) MarshalBinary() (data []byte, err error) {
+func (output *Output) ObjectStorageValue() (data []byte) {
 	// determine amount of balances in the output
 	balanceCount := len(output.balances)
 
@@ -75,38 +124,10 @@ func (output *Output) MarshalBinary() (data []byte, err error) {
 	return
 }
 
-// UnmarshalBinary restores a Output from a serialized version in the ObjectStorage with parts of the object
+// UnmarshalObjectStorageValue restores a Output from a serialized version in the ObjectStorage with parts of the object
 // being stored in its key rather than the content of the database to reduce storage requirements.
-func (output *Output) UnmarshalBinary(data []byte) (err error) {
-	// check if the storageKey has been set
-	if output.storageKey == nil {
-		return fmt.Errorf("missing storageKey when trying to unmarshal Output (it contains part of the information)")
-	}
-
-	// parse information from storageKey
-	storageKeyUnmarshaler := marshalutil.New(output.storageKey)
-	output.address, err = address.Parse(storageKeyUnmarshaler)
-	if err != nil {
-		return
-	}
-	output.transactionId, err = ParseId(storageKeyUnmarshaler)
-	if err != nil {
-		return
-	}
-
-	// parse information from content bytes
-	contentUnmarshaler := marshalutil.New(data)
-	balanceCount, err := contentUnmarshaler.ReadUint32()
-	if err != nil {
-		return
-	}
-	output.balances = make([]*balance.Balance, balanceCount)
-	for i := uint32(0); i < balanceCount; i++ {
-		output.balances[i], err = balance.Parse(contentUnmarshaler)
-		if err != nil {
-			return
-		}
-	}
+func (output *Output) UnmarshalObjectStorageValue(data []byte) (err error) {
+	_, err, _ = OutputFromBytes(marshalutil.New(output.storageKey).WriteBytes(data).Bytes(), output)
 
 	return
 }
@@ -116,9 +137,9 @@ func (output *Output) Update(other objectstorage.StorableObject) {
 	panic("this object should never be updated")
 }
 
-// GetStorageKey returns the key that is used to store the object in the database.
+// ObjectStorageKey returns the key that is used to store the object in the database.
 // It is required to match StorableObject interface.
-func (output *Output) GetStorageKey() []byte {
+func (output *Output) ObjectStorageKey() []byte {
 	return output.storageKey
 }
 
diff --git a/packages/binary/valuetransfer/transaction/transaction.go b/packages/binary/valuetransfer/transaction/transaction.go
index 705a62ab8278e0bda05a23b95914aa91188853f3..664b8bb0d4a99aa09b32cb26184fed8e83b818bf 100644
--- a/packages/binary/valuetransfer/transaction/transaction.go
+++ b/packages/binary/valuetransfer/transaction/transaction.go
@@ -280,7 +280,7 @@ func (transaction *Transaction) String() string {
 // define contract (ensure that the struct fulfills the given interface)
 var _ objectstorage.StorableObject = &Transaction{}
 
-func (transaction *Transaction) GetStorageKey() []byte {
+func (transaction *Transaction) ObjectStorageKey() []byte {
 	id := transaction.Id()
 
 	return id[:]
@@ -290,12 +290,12 @@ func (transaction *Transaction) Update(other objectstorage.StorableObject) {
 	panic("update forbidden")
 }
 
-// MarshalBinary returns a bytes representation of the Transaction by implementing the encoding.BinaryMarshaler interface.
-func (transaction *Transaction) MarshalBinary() ([]byte, error) {
-	return transaction.Bytes(), nil
+// ObjectStorageValue returns a bytes representation of the Transaction by implementing the encoding.BinaryMarshaler interface.
+func (transaction *Transaction) ObjectStorageValue() []byte {
+	return transaction.Bytes()
 }
 
-func (transaction *Transaction) UnmarshalBinary(bytes []byte) (err error) {
+func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (err error) {
 	_, err, _ = FromBytes(bytes, transaction)
 
 	return