diff --git a/packages/model/meta_transaction/constants.go b/packages/model/meta_transaction/constants.go
new file mode 100644
index 0000000000000000000000000000000000000000..3db3cb053683b7958a0d491fb92b8cd3990416db
--- /dev/null
+++ b/packages/model/meta_transaction/constants.go
@@ -0,0 +1,29 @@
+package meta_transaction
+
+const (
+	SHARD_MARKER_OFFSET            = 0
+	TRUNK_TRANSACTION_HASH_OFFSET  = SHARD_MARKER_END
+	BRANCH_TRANSACTION_HASH_OFFSET = TRUNK_TRANSACTION_HASH_END
+	HEAD_OFFSET                    = BRANCH_TRANSACTION_HASH_END
+	TAIL_OFFSET                    = HEAD_END
+	TRANSACTION_TYPE_OFFSET        = TAIL_END
+	DATA_OFFSET                    = TRANSACTION_TYPE_END
+
+	SHARD_MARKER_SIZE            = 12
+	TRUNK_TRANSACTION_HASH_SIZE  = 243
+	BRANCH_TRANSACTION_HASH_SIZE = 243
+	HEAD_SIZE                    = 1
+	TAIL_SIZE                    = 1
+	TRANSACTION_TYPE_SIZE        = 22
+	DATA_SIZE                    = 5000
+
+	SHARD_MARKER_END            = SHARD_MARKER_OFFSET + SHARD_MARKER_SIZE
+	TRUNK_TRANSACTION_HASH_END  = TRUNK_TRANSACTION_HASH_OFFSET + TRUNK_TRANSACTION_HASH_SIZE
+	BRANCH_TRANSACTION_HASH_END = BRANCH_TRANSACTION_HASH_OFFSET + BRANCH_TRANSACTION_HASH_SIZE
+	HEAD_END                    = HEAD_OFFSET + HEAD_SIZE
+	TAIL_END                    = TAIL_OFFSET + TAIL_SIZE
+	TRANSACTION_TYPE_END        = TRANSACTION_TYPE_OFFSET + TRANSACTION_TYPE_SIZE
+	DATA_END                    = DATA_OFFSET + DATA_SIZE
+
+	MARSHALLED_TOTAL_SIZE = DATA_END
+)
diff --git a/packages/model/meta_transaction/meta_transaction.go b/packages/model/meta_transaction/meta_transaction.go
new file mode 100644
index 0000000000000000000000000000000000000000..ea8e83b8abca89924fb9bd09b8f96e76a1e33ef9
--- /dev/null
+++ b/packages/model/meta_transaction/meta_transaction.go
@@ -0,0 +1,480 @@
+package meta_transaction
+
+import (
+	"sync"
+
+	"github.com/iotaledger/goshimmer/packages/curl"
+	"github.com/iotaledger/goshimmer/packages/ternary"
+)
+
+type MetaTransaction struct {
+	hash            *ternary.Trinary
+	weightMagnitude int
+
+	shardMarker           *ternary.Trinary
+	trunkTransactionHash  *ternary.Trinary
+	branchTransactionHash *ternary.Trinary
+	head                  *bool
+	tail                  *bool
+	transactionType       *ternary.Trinary
+	data                  ternary.Trits
+	modified              bool
+
+	hasherMutex                sync.RWMutex
+	hashMutex                  sync.RWMutex
+	shardMarkerMutex           sync.RWMutex
+	trunkTransactionHashMutex  sync.RWMutex
+	branchTransactionHashMutex sync.RWMutex
+	headMutex                  sync.RWMutex
+	tailMutex                  sync.RWMutex
+	transactionTypeMutex       sync.RWMutex
+	dataMutex                  sync.RWMutex
+	bytesMutex                 sync.RWMutex
+	modifiedMutex              sync.RWMutex
+
+	trits ternary.Trits
+	bytes []byte
+}
+
+func New() *MetaTransaction {
+	return FromTrits(make(ternary.Trits, MARSHALLED_TOTAL_SIZE))
+}
+
+func FromTrits(trits ternary.Trits) *MetaTransaction {
+	return &MetaTransaction{
+		trits: trits,
+	}
+}
+
+func FromBytes(bytes []byte) (result *MetaTransaction) {
+	result = FromTrits(ternary.BytesToTrits(bytes)[:MARSHALLED_TOTAL_SIZE])
+	result.bytes = bytes
+
+	return
+}
+
+func (this *MetaTransaction) LockHasher() {
+	this.hasherMutex.RLock()
+}
+
+func (this *MetaTransaction) UnlockHasher() {
+	this.hasherMutex.RUnlock()
+}
+
+func (this *MetaTransaction) ReHash() {
+	this.hashMutex.Lock()
+	defer this.hashMutex.Unlock()
+	this.hash = nil
+
+	this.bytesMutex.Lock()
+	defer this.bytesMutex.Unlock()
+	this.bytes = nil
+}
+
+// retrieves the hash of the transaction
+func (this *MetaTransaction) GetHash() (result ternary.Trinary) {
+	this.hashMutex.RLock()
+	if this.hash == nil {
+		this.hashMutex.RUnlock()
+		this.hashMutex.Lock()
+		defer this.hashMutex.Unlock()
+		if this.hash == nil {
+			this.hasherMutex.Lock()
+			this.parseHashRelatedDetails()
+			this.hasherMutex.Unlock()
+		}
+	} else {
+		defer this.hashMutex.RUnlock()
+	}
+
+	result = *this.hash
+
+	return
+}
+
+// retrieves weight magnitude of the transaction (amount of pow invested)
+func (this *MetaTransaction) GetWeightMagnitude() (result int) {
+	this.hashMutex.RLock()
+	if this.hash == nil {
+		this.hashMutex.RUnlock()
+		this.hashMutex.Lock()
+		defer this.hashMutex.Unlock()
+		if this.hash == nil {
+			this.hasherMutex.Lock()
+			this.parseHashRelatedDetails()
+			this.hasherMutex.Unlock()
+		}
+	} else {
+		defer this.hashMutex.RUnlock()
+	}
+
+	result = this.weightMagnitude
+
+	return
+}
+
+// hashes the transaction using curl (without locking - internal usage)
+func (this *MetaTransaction) parseHashRelatedDetails() {
+	hashTrits := <-curl.CURLP81.Hash(this.trits)
+	hashTrinary := hashTrits.ToTrinary()
+
+	this.hash = &hashTrinary
+	this.weightMagnitude = hashTrits.TrailingZeroes()
+
+	return
+}
+
+// getter for the shard marker (supports concurrency)
+func (this *MetaTransaction) GetShardMarker() (result ternary.Trinary) {
+	this.shardMarkerMutex.RLock()
+	if this.shardMarker == nil {
+		this.shardMarkerMutex.RUnlock()
+		this.shardMarkerMutex.Lock()
+		defer this.shardMarkerMutex.Unlock()
+		if this.shardMarker == nil {
+			shardMarker := this.trits[SHARD_MARKER_OFFSET:SHARD_MARKER_END].ToTrinary()
+
+			this.shardMarker = &shardMarker
+		}
+	} else {
+		defer this.shardMarkerMutex.RUnlock()
+	}
+
+	result = *this.shardMarker
+
+	return
+}
+
+// setter for the shard marker (supports concurrency)
+func (this *MetaTransaction) SetShardMarker(shardMarker ternary.Trinary) bool {
+	this.shardMarkerMutex.RLock()
+	if this.shardMarker == nil || *this.shardMarker != shardMarker {
+		this.shardMarkerMutex.RUnlock()
+		this.shardMarkerMutex.Lock()
+		defer this.shardMarkerMutex.Unlock()
+		if this.shardMarker == nil || *this.shardMarker != shardMarker {
+			this.shardMarker = &shardMarker
+
+			this.hasherMutex.RLock()
+			copy(this.trits[SHARD_MARKER_OFFSET:SHARD_MARKER_END], shardMarker.ToTrits()[:SHARD_MARKER_SIZE])
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.shardMarkerMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the bundleHash (supports concurrency)
+func (this *MetaTransaction) GetTrunkTransactionHash() (result ternary.Trinary) {
+	this.trunkTransactionHashMutex.RLock()
+	if this.trunkTransactionHash == nil {
+		this.trunkTransactionHashMutex.RUnlock()
+		this.trunkTransactionHashMutex.Lock()
+		defer this.trunkTransactionHashMutex.Unlock()
+		if this.trunkTransactionHash == nil {
+			trunkTransactionHash := this.trits[TRUNK_TRANSACTION_HASH_OFFSET:TRUNK_TRANSACTION_HASH_END].ToTrinary()
+
+			this.trunkTransactionHash = &trunkTransactionHash
+		}
+	} else {
+		defer this.trunkTransactionHashMutex.RUnlock()
+	}
+
+	result = *this.trunkTransactionHash
+
+	return
+}
+
+// setter for the trunkTransactionHash (supports concurrency)
+func (this *MetaTransaction) SetTrunkTransactionHash(trunkTransactionHash ternary.Trinary) bool {
+	this.trunkTransactionHashMutex.RLock()
+	if this.trunkTransactionHash == nil || *this.trunkTransactionHash != trunkTransactionHash {
+		this.trunkTransactionHashMutex.RUnlock()
+		this.trunkTransactionHashMutex.Lock()
+		defer this.trunkTransactionHashMutex.Unlock()
+		if this.trunkTransactionHash == nil || *this.trunkTransactionHash != trunkTransactionHash {
+			this.trunkTransactionHash = &trunkTransactionHash
+
+			this.hasherMutex.RLock()
+			copy(this.trits[TRUNK_TRANSACTION_HASH_OFFSET:TRUNK_TRANSACTION_HASH_END], trunkTransactionHash.ToTrits()[:TRUNK_TRANSACTION_HASH_SIZE])
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.trunkTransactionHashMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the bundleHash (supports concurrency)
+func (this *MetaTransaction) GetBranchTransactionHash() (result ternary.Trinary) {
+	this.branchTransactionHashMutex.RLock()
+	if this.branchTransactionHash == nil {
+		this.branchTransactionHashMutex.RUnlock()
+		this.branchTransactionHashMutex.Lock()
+		defer this.branchTransactionHashMutex.Unlock()
+		if this.branchTransactionHash == nil {
+			branchTransactionHash := this.trits[BRANCH_TRANSACTION_HASH_OFFSET:BRANCH_TRANSACTION_HASH_END].ToTrinary()
+
+			this.branchTransactionHash = &branchTransactionHash
+		}
+	} else {
+		defer this.branchTransactionHashMutex.RUnlock()
+	}
+
+	result = *this.branchTransactionHash
+
+	return
+}
+
+// setter for the trunkTransactionHash (supports concurrency)
+func (this *MetaTransaction) SetBranchTransactionHash(branchTransactionHash ternary.Trinary) bool {
+	this.branchTransactionHashMutex.RLock()
+	if this.branchTransactionHash == nil || *this.branchTransactionHash != branchTransactionHash {
+		this.branchTransactionHashMutex.RUnlock()
+		this.branchTransactionHashMutex.Lock()
+		defer this.branchTransactionHashMutex.Unlock()
+		if this.branchTransactionHash == nil || *this.branchTransactionHash != branchTransactionHash {
+			this.branchTransactionHash = &branchTransactionHash
+
+			this.hasherMutex.RLock()
+			copy(this.trits[BRANCH_TRANSACTION_HASH_OFFSET:BRANCH_TRANSACTION_HASH_END], branchTransactionHash.ToTrits()[:BRANCH_TRANSACTION_HASH_SIZE])
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.branchTransactionHashMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the head flag (supports concurrency)
+func (this *MetaTransaction) GetHead() (result bool) {
+	this.headMutex.RLock()
+	if this.head == nil {
+		this.headMutex.RUnlock()
+		this.headMutex.Lock()
+		defer this.headMutex.Unlock()
+		if this.head == nil {
+			head := this.trits[HEAD_OFFSET] == 1
+
+			this.head = &head
+		}
+	} else {
+		defer this.headMutex.RUnlock()
+	}
+
+	result = *this.head
+
+	return
+}
+
+// setter for the head flag (supports concurrency)
+func (this *MetaTransaction) SetHead(head bool) bool {
+	this.headMutex.RLock()
+	if this.head == nil || *this.head != head {
+		this.headMutex.RUnlock()
+		this.headMutex.Lock()
+		defer this.headMutex.Unlock()
+		if this.head == nil || *this.head != head {
+			this.head = &head
+
+			this.hasherMutex.RLock()
+			if head {
+				this.trits[HEAD_OFFSET] = 1
+			} else {
+				this.trits[HEAD_OFFSET] = 0
+			}
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.headMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the tail flag (supports concurrency)
+func (this *MetaTransaction) GetTail() (result bool) {
+	this.tailMutex.RLock()
+	if this.tail == nil {
+		this.tailMutex.RUnlock()
+		this.tailMutex.Lock()
+		defer this.tailMutex.Unlock()
+		if this.tail == nil {
+			tail := this.trits[TAIL_OFFSET] == 1
+
+			this.tail = &tail
+		}
+	} else {
+		defer this.tailMutex.RUnlock()
+	}
+
+	result = *this.tail
+
+	return
+}
+
+// setter for the tail flag (supports concurrency)
+func (this *MetaTransaction) SetTail(tail bool) bool {
+	this.tailMutex.RLock()
+	if this.tail == nil || *this.tail != tail {
+		this.tailMutex.RUnlock()
+		this.tailMutex.Lock()
+		defer this.tailMutex.Unlock()
+		if this.tail == nil || *this.tail != tail {
+			this.tail = &tail
+
+			this.hasherMutex.RLock()
+			if tail {
+				this.trits[TAIL_OFFSET] = 1
+			} else {
+				this.trits[TAIL_OFFSET] = 0
+			}
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.tailMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the transaction type (supports concurrency)
+func (this *MetaTransaction) GetTransactionType() (result ternary.Trinary) {
+	this.transactionTypeMutex.RLock()
+	if this.transactionType == nil {
+		this.transactionTypeMutex.RUnlock()
+		this.transactionTypeMutex.Lock()
+		defer this.transactionTypeMutex.Unlock()
+		if this.transactionType == nil {
+			transactionType := this.trits[TRANSACTION_TYPE_OFFSET:TRANSACTION_TYPE_END].ToTrinary()
+
+			this.transactionType = &transactionType
+		}
+	} else {
+		defer this.transactionTypeMutex.RUnlock()
+	}
+
+	result = *this.transactionType
+
+	return
+}
+
+// setter for the transaction type (supports concurrency)
+func (this *MetaTransaction) SetTransactionType(transactionType ternary.Trinary) bool {
+	this.transactionTypeMutex.RLock()
+	if this.transactionType == nil || *this.transactionType != transactionType {
+		this.transactionTypeMutex.RUnlock()
+		this.transactionTypeMutex.Lock()
+		defer this.transactionTypeMutex.Unlock()
+		if this.transactionType == nil || *this.transactionType != transactionType {
+			this.transactionType = &transactionType
+
+			this.hasherMutex.RLock()
+			copy(this.trits[TRANSACTION_TYPE_OFFSET:TRANSACTION_TYPE_END], transactionType.ToTrits()[:TRANSACTION_TYPE_SIZE])
+			this.hasherMutex.RUnlock()
+
+			this.SetModified(true)
+			this.ReHash()
+
+			return true
+		}
+	} else {
+		this.transactionTypeMutex.RUnlock()
+	}
+
+	return false
+}
+
+// getter for the data slice (supports concurrency)
+func (this *MetaTransaction) GetData() (result ternary.Trits) {
+	this.dataMutex.RLock()
+	if this.data == nil {
+		this.dataMutex.RUnlock()
+		this.dataMutex.Lock()
+		defer this.dataMutex.Unlock()
+		if this.data == nil {
+			this.data = this.trits[DATA_OFFSET:DATA_END]
+		}
+	} else {
+		defer this.dataMutex.RUnlock()
+	}
+
+	result = this.data
+
+	return
+}
+
+func (this *MetaTransaction) GetTrits() (result ternary.Trits) {
+	result = make(ternary.Trits, len(this.trits))
+
+	this.hasherMutex.Lock()
+	copy(result, this.trits)
+	this.hasherMutex.Unlock()
+
+	return
+}
+
+func (this *MetaTransaction) GetBytes() (result []byte) {
+	this.bytesMutex.RLock()
+	if this.bytes == nil {
+		this.bytesMutex.RUnlock()
+		this.bytesMutex.Lock()
+		defer this.bytesMutex.Unlock()
+
+		this.hasherMutex.Lock()
+		this.bytes = this.trits.ToBytes()
+		this.hasherMutex.Unlock()
+	} else {
+		this.hasherMutex.RUnlock()
+	}
+
+	result = make([]byte, len(this.bytes))
+	copy(result, this.bytes)
+
+	return
+}
+
+// returns true if the transaction contains unsaved changes (supports concurrency)
+func (this *MetaTransaction) GetModified() bool {
+	this.modifiedMutex.RLock()
+	defer this.modifiedMutex.RUnlock()
+
+	return this.modified
+}
+
+// sets the modified flag which controls if a transaction is going to be saved (supports concurrency)
+func (this *MetaTransaction) SetModified(modified bool) {
+	this.modifiedMutex.Lock()
+	defer this.modifiedMutex.Unlock()
+
+	this.modified = modified
+}
diff --git a/packages/model/meta_transaction/meta_transaction_test.go b/packages/model/meta_transaction/meta_transaction_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..dd54c2b2245cf96c0bf88bc17da799fb1c9c1def
--- /dev/null
+++ b/packages/model/meta_transaction/meta_transaction_test.go
@@ -0,0 +1,54 @@
+package meta_transaction
+
+import (
+	"fmt"
+	"sync"
+	"testing"
+
+	"github.com/iotaledger/goshimmer/packages/ternary"
+	"github.com/magiconair/properties/assert"
+)
+
+func TestMetaTransaction_SettersGetters(t *testing.T) {
+	shardMarker := ternary.Trinary("NPHTQORL9XKA")
+	trunkTransactionHash := ternary.Trinary("99999999999999999999999999999999999999999999999999999999999999999999999999999999A")
+	branchTransactionHash := ternary.Trinary("99999999999999999999999999999999999999999999999999999999999999999999999999999999B")
+	head := true
+	tail := true
+	transactionType := ternary.Trinary("9999999999999999999999")
+
+	transaction := New()
+	transaction.SetShardMarker(shardMarker)
+	transaction.SetTrunkTransactionHash(trunkTransactionHash)
+	transaction.SetBranchTransactionHash(branchTransactionHash)
+	transaction.SetHead(head)
+	transaction.SetTail(tail)
+	transaction.SetTransactionType(transactionType)
+
+	assert.Equal(t, transaction.GetWeightMagnitude(), 0)
+	assert.Equal(t, transaction.GetShardMarker(), shardMarker)
+	assert.Equal(t, transaction.GetTrunkTransactionHash(), trunkTransactionHash)
+	assert.Equal(t, transaction.GetBranchTransactionHash(), branchTransactionHash)
+	assert.Equal(t, transaction.GetHead(), head)
+	assert.Equal(t, transaction.GetTail(), tail)
+	assert.Equal(t, transaction.GetTransactionType(), transactionType)
+	assert.Equal(t, transaction.GetHash(), FromBytes(transaction.GetBytes()).GetHash())
+
+	fmt.Println(transaction.GetHash())
+}
+
+func BenchmarkMetaTransaction_GetHash(b *testing.B) {
+	var waitGroup sync.WaitGroup
+
+	for i := 0; i < b.N; i++ {
+		go func() {
+			waitGroup.Add(1)
+
+			New().GetHash()
+
+			waitGroup.Done()
+		}()
+	}
+
+	waitGroup.Wait()
+}
diff --git a/packages/model/value_transaction/value_transaction.go b/packages/model/value_transaction/value_transaction.go
new file mode 100644
index 0000000000000000000000000000000000000000..337f003c2c1f5ad525d794305c12dbe10abae1a9
--- /dev/null
+++ b/packages/model/value_transaction/value_transaction.go
@@ -0,0 +1,22 @@
+package value_transaction
+
+import (
+	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
+	"github.com/iotaledger/goshimmer/packages/ternary"
+)
+
+type ValueTransaction struct {
+	*meta_transaction.MetaTransaction
+
+	data ternary.Trits
+}
+
+func New() (result *ValueTransaction) {
+	result = &ValueTransaction{
+		MetaTransaction: meta_transaction.New(),
+	}
+
+	result.data = result.MetaTransaction.GetData()
+
+	return
+}
diff --git a/packages/model/value_transaction/value_transaction_test.go b/packages/model/value_transaction/value_transaction_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f81aa1ab02c1e79d988577c480c5d077f38bd1b3
--- /dev/null
+++ b/packages/model/value_transaction/value_transaction_test.go
@@ -0,0 +1,34 @@
+package value_transaction
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/iotaledger/goshimmer/packages/ternary"
+	"github.com/magiconair/properties/assert"
+)
+
+func TestMetaTransaction_SettersGetters(t *testing.T) {
+	shardMarker := ternary.Trinary("NPHTQORL9XKA")
+	trunkTransactionHash := ternary.Trinary("99999999999999999999999999999999999999999999999999999999999999999999999999999999A")
+	branchTransactionHash := ternary.Trinary("99999999999999999999999999999999999999999999999999999999999999999999999999999999B")
+	head := true
+	tail := true
+
+	transaction := New()
+	transaction.SetShardMarker(shardMarker)
+	transaction.SetTrunkTransactionHash(trunkTransactionHash)
+	transaction.SetBranchTransactionHash(branchTransactionHash)
+	transaction.SetHead(head)
+	transaction.SetTail(tail)
+
+	assert.Equal(t, transaction.GetWeightMagnitude(), 0)
+	assert.Equal(t, transaction.GetShardMarker(), shardMarker)
+	assert.Equal(t, transaction.GetTrunkTransactionHash(), trunkTransactionHash)
+	assert.Equal(t, transaction.GetBranchTransactionHash(), branchTransactionHash)
+	assert.Equal(t, transaction.GetHead(), head)
+	assert.Equal(t, transaction.GetTail(), tail)
+	//assert.Equal(t, transaction.GetHash(), FromBytes(transaction.GetBytes()).GetHash())
+
+	fmt.Println(transaction.GetHash())
+}