From c9c83bd188ea373c538272aa8aab96a17cd62748 Mon Sep 17 00:00:00 2001
From: Hans Moog <hm@mkjc.net>
Date: Fri, 14 Feb 2020 19:03:14 +0100
Subject: [PATCH] Feat: started to merge changes

---
 go.mod                                        |   5 +-
 go.sum                                        |   2 +
 main.go                                       |  58 ++--
 packages/binary/datastructure/random_map.go   | 129 +++++++++
 .../binary/storageprefix/storageprefix.go     |  24 +-
 .../model/transaction/cached_transaction.go   |   2 +-
 packages/binary/tangle/tipselector/events.go  |  15 +
 .../binary/tangle/tipselector/tipselector.go  |  68 +++++
 .../tangle/tipselector/tipselector_test.go    |  51 ++++
 packages/gossip/manager.go                    |   6 +-
 plugins/bundleprocessor/bundleprocessor.go    | 101 -------
 .../bundleprocessor/bundleprocessor_test.go   | 143 ----------
 plugins/bundleprocessor/errors.go             |   7 -
 plugins/bundleprocessor/events.go             |  27 --
 plugins/bundleprocessor/plugin.go             |  52 ----
 .../bundleprocessor/valuebundleprocessor.go   |  80 ------
 plugins/gossip/gossip.go                      |  30 +-
 plugins/gossip/plugin.go                      |  24 +-
 plugins/graph/plugin.go                       |   6 +-
 plugins/spa/explorer_routes.go                |  50 ++--
 plugins/tangle/approvers.go                   | 128 ---------
 plugins/tangle/bundle.go                      | 133 ---------
 plugins/tangle/errors.go                      |   7 -
 plugins/tangle/events.go                      |  18 --
 plugins/tangle/misc.go                        |  16 --
 plugins/tangle/plugin.go                      |  67 -----
 plugins/tangle/solidifier.go                  | 265 ------------------
 plugins/tangle/solidifier_test.go             | 140 ---------
 plugins/tangle/tangle.go                      |  71 +++++
 plugins/tangle/transaction.go                 | 124 --------
 plugins/tangle/transaction_metadata.go        | 134 ---------
 plugins/tangle/tx_per_address.go              |  59 ----
 plugins/tangle/unsolidTxs.go                  |  59 ----
 plugins/tipselection/plugin.go                |  27 --
 plugins/tipselection/tipselection.go          |  54 ----
 plugins/tipselection/tipselection_test.go     |  81 ------
 .../webapi/findTransactionHashes/plugin.go    |  38 +--
 .../getTransactionObjectsByHash/plugin.go     |   4 +-
 .../getTransactionTrytesByHash/plugin.go      |   4 +-
 39 files changed, 458 insertions(+), 1851 deletions(-)
 create mode 100644 packages/binary/datastructure/random_map.go
 create mode 100644 packages/binary/tangle/tipselector/events.go
 create mode 100644 packages/binary/tangle/tipselector/tipselector.go
 create mode 100644 packages/binary/tangle/tipselector/tipselector_test.go
 delete mode 100644 plugins/bundleprocessor/bundleprocessor.go
 delete mode 100644 plugins/bundleprocessor/bundleprocessor_test.go
 delete mode 100644 plugins/bundleprocessor/errors.go
 delete mode 100644 plugins/bundleprocessor/events.go
 delete mode 100644 plugins/bundleprocessor/plugin.go
 delete mode 100644 plugins/bundleprocessor/valuebundleprocessor.go
 delete mode 100644 plugins/tangle/approvers.go
 delete mode 100644 plugins/tangle/bundle.go
 delete mode 100644 plugins/tangle/errors.go
 delete mode 100644 plugins/tangle/events.go
 delete mode 100644 plugins/tangle/misc.go
 delete mode 100644 plugins/tangle/plugin.go
 delete mode 100644 plugins/tangle/solidifier.go
 delete mode 100644 plugins/tangle/solidifier_test.go
 create mode 100644 plugins/tangle/tangle.go
 delete mode 100644 plugins/tangle/transaction.go
 delete mode 100644 plugins/tangle/transaction_metadata.go
 delete mode 100644 plugins/tangle/tx_per_address.go
 delete mode 100644 plugins/tangle/unsolidTxs.go
 delete mode 100644 plugins/tipselection/plugin.go
 delete mode 100644 plugins/tipselection/tipselection.go
 delete mode 100644 plugins/tipselection/tipselection_test.go

diff --git a/go.mod b/go.mod
index 7afa104f..c51b84bd 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,11 @@ module github.com/iotaledger/goshimmer
 go 1.13
 
 require (
-	cloud.google.com/go v0.36.0 // indirect
 	github.com/dgraph-io/badger/v2 v2.0.1
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/dgryski/go-farm v0.0.0-20191112170834-c2139c5d712b // indirect
 	github.com/gobuffalo/envy v1.8.1 // indirect
-	github.com/gobuffalo/logger v1.0.3 // indirect
+	github.com/gobuffalo/logger v1.0.3
 	github.com/gobuffalo/packr/v2 v2.7.1
 	github.com/golang/protobuf v1.3.2
 	github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2
@@ -37,12 +36,12 @@ require (
 	github.com/valyala/fasttemplate v1.1.0 // indirect
 	go.uber.org/atomic v1.5.1
 	go.uber.org/zap v1.13.0
+	golang.org/dl v0.0.0-20200212233958-09d79dcf4807 // indirect
 	golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
 	golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
 	golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
 	golang.org/x/text v0.3.2 // indirect
 	golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 // indirect
-	google.golang.org/appengine v1.4.0 // indirect
 	gopkg.in/ini.v1 v1.51.1 // indirect
 	gopkg.in/yaml.v2 v2.2.7 // indirect
 )
diff --git a/go.sum b/go.sum
index d8296fac..a72469bc 100644
--- a/go.sum
+++ b/go.sum
@@ -314,6 +314,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
 go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
+golang.org/dl v0.0.0-20200212233958-09d79dcf4807 h1:P3ZXCWM1Xdo1ZUpMAM/KocwYgn5r/cKxffvaoYUlfYE=
+golang.org/dl v0.0.0-20200212233958-09d79dcf4807/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
 golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
diff --git a/main.go b/main.go
index 2f947172..32513b07 100644
--- a/main.go
+++ b/main.go
@@ -4,27 +4,14 @@ import (
 	"net/http"
 	_ "net/http/pprof"
 
-	"github.com/iotaledger/goshimmer/plugins/analysis"
+	"github.com/iotaledger/goshimmer/plugins/gracefulshutdown"
+
+	"github.com/iotaledger/goshimmer/plugins/tangle"
+
 	"github.com/iotaledger/goshimmer/plugins/autopeering"
-	"github.com/iotaledger/goshimmer/plugins/bundleprocessor"
 	"github.com/iotaledger/goshimmer/plugins/cli"
 	"github.com/iotaledger/goshimmer/plugins/gossip"
-	"github.com/iotaledger/goshimmer/plugins/gracefulshutdown"
-	"github.com/iotaledger/goshimmer/plugins/graph"
-	"github.com/iotaledger/goshimmer/plugins/metrics"
 	"github.com/iotaledger/goshimmer/plugins/remotelog"
-	"github.com/iotaledger/goshimmer/plugins/spa"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/goshimmer/plugins/tipselection"
-	"github.com/iotaledger/goshimmer/plugins/webapi"
-	webapi_broadcastData "github.com/iotaledger/goshimmer/plugins/webapi/broadcastData"
-	webapi_findTransactionHashes "github.com/iotaledger/goshimmer/plugins/webapi/findTransactionHashes"
-	webapi_getNeighbors "github.com/iotaledger/goshimmer/plugins/webapi/getNeighbors"
-	webapi_getTransactionObjectsByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionObjectsByHash"
-	webapi_getTransactionTrytesByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionTrytesByHash"
-	webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta"
-	webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer"
-	webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth"
 	"github.com/iotaledger/hive.go/node"
 )
 
@@ -39,27 +26,28 @@ func main() {
 			remotelog.PLUGIN,
 
 			autopeering.PLUGIN,
-			gossip.PLUGIN,
 			tangle.PLUGIN,
-			bundleprocessor.PLUGIN,
-			analysis.PLUGIN,
+			gossip.PLUGIN,
 			gracefulshutdown.PLUGIN,
-			tipselection.PLUGIN,
-			metrics.PLUGIN,
-
-			webapi.PLUGIN,
-			webapi_auth.PLUGIN,
-			webapi_gtta.PLUGIN,
-			webapi_spammer.PLUGIN,
-			webapi_broadcastData.PLUGIN,
-			webapi_getTransactionTrytesByHash.PLUGIN,
-			webapi_getTransactionObjectsByHash.PLUGIN,
-			webapi_findTransactionHashes.PLUGIN,
-			webapi_getNeighbors.PLUGIN,
-			webapi_spammer.PLUGIN,
 
-			spa.PLUGIN,
-			graph.PLUGIN,
+			/*
+				analysis.PLUGIN,
+				metrics.PLUGIN,
+
+				webapi.PLUGIN,
+				webapi_auth.PLUGIN,
+				webapi_gtta.PLUGIN,
+				webapi_spammer.PLUGIN,
+				webapi_broadcastData.PLUGIN,
+				webapi_getTransactionTrytesByHash.PLUGIN,
+				webapi_getTransactionObjectsByHash.PLUGIN,
+				webapi_findTransactionHashes.PLUGIN,
+				webapi_getNeighbors.PLUGIN,
+				webapi_spammer.PLUGIN,
+
+				//spa.PLUGIN,
+				//graph.PLUGIN,
+			*/
 		),
 	)
 }
diff --git a/packages/binary/datastructure/random_map.go b/packages/binary/datastructure/random_map.go
new file mode 100644
index 00000000..ff1692c4
--- /dev/null
+++ b/packages/binary/datastructure/random_map.go
@@ -0,0 +1,129 @@
+package datastructure
+
+import (
+	"math/rand"
+	"sync"
+	"time"
+)
+
+func init() {
+	rand.Seed(time.Now().UnixNano())
+}
+
+type randomMapEntry struct {
+	key      interface{}
+	value    interface{}
+	keyIndex int
+}
+
+type RandomMap struct {
+	rawMap map[interface{}]*randomMapEntry
+	keys   []interface{}
+	size   int
+	mutex  sync.RWMutex
+}
+
+func NewRandomMap() *RandomMap {
+	return &RandomMap{
+		rawMap: make(map[interface{}]*randomMapEntry),
+		keys:   make([]interface{}, 0),
+	}
+}
+
+func (rmap *RandomMap) Set(key interface{}, value interface{}) (updated bool) {
+	rmap.mutex.Lock()
+
+	if entry, exists := rmap.rawMap[key]; exists {
+		if entry.value != value {
+			entry.value = value
+
+			updated = true
+		}
+	} else {
+		rmap.rawMap[key] = &randomMapEntry{
+			key:      key,
+			value:    value,
+			keyIndex: rmap.size,
+		}
+
+		updated = true
+
+		rmap.keys = append(rmap.keys, key)
+
+		rmap.size++
+	}
+
+	rmap.mutex.Unlock()
+
+	return
+}
+
+func (rmap *RandomMap) Get(key interface{}) (result interface{}, exists bool) {
+	rmap.mutex.RLock()
+
+	if entry, entryExists := rmap.rawMap[key]; entryExists {
+		result = entry.value
+		exists = entryExists
+	}
+
+	rmap.mutex.RUnlock()
+
+	return
+}
+
+func (rmap *RandomMap) Delete(key interface{}) (result interface{}, exists bool) {
+	rmap.mutex.RLock()
+
+	if _, entryExists := rmap.rawMap[key]; entryExists {
+		rmap.mutex.RUnlock()
+		rmap.mutex.Lock()
+
+		if entry, entryExists := rmap.rawMap[key]; entryExists {
+			delete(rmap.rawMap, key)
+
+			rmap.size--
+
+			if entry.keyIndex != rmap.size {
+				oldKey := entry.keyIndex
+				movedKey := rmap.keys[rmap.size]
+
+				rmap.rawMap[movedKey].keyIndex = oldKey
+
+				rmap.keys[oldKey] = movedKey
+			}
+
+			rmap.keys = rmap.keys[:rmap.size]
+
+			result = entry.value
+			exists = true
+		}
+
+		rmap.mutex.Unlock()
+	} else {
+		rmap.mutex.RUnlock()
+	}
+
+	return
+}
+
+func (rmap *RandomMap) Size() (result int) {
+	rmap.mutex.RLock()
+
+	result = rmap.size
+
+	rmap.mutex.RUnlock()
+
+	return
+}
+
+func (rmap *RandomMap) RandomEntry() (result interface{}) {
+	rmap.mutex.RLock()
+
+	if rmap.size >= 1 {
+		result = rmap.rawMap[rmap.keys[rand.Intn(rmap.size)]].value
+	}
+
+	rmap.mutex.RUnlock()
+
+	return
+}
diff --git a/packages/binary/storageprefix/storageprefix.go b/packages/binary/storageprefix/storageprefix.go
index 1e55f2db..6493adf6 100644
--- a/packages/binary/storageprefix/storageprefix.go
+++ b/packages/binary/storageprefix/storageprefix.go
@@ -1,17 +1,19 @@
 package storageprefix
 
 var (
-	TangleTransaction         = []byte{0}
-	TangleTransactionMetadata = []byte{1}
-	TangleApprovers           = []byte{2}
-	TangleMissingTransaction  = []byte{3}
+	Mainnet = []byte{0}
 
-	ValueTangleTransferMetadata = []byte{4}
-	ValueTangleConsumers        = []byte{5}
-	ValueTangleMissingTransfers = []byte{6}
+	TangleTransaction         = []byte{1}
+	TangleTransactionMetadata = []byte{2}
+	TangleApprovers           = []byte{3}
+	TangleMissingTransaction  = []byte{4}
 
-	LedgerStateTransferOutput        = []byte{7}
-	LedgerStateTransferOutputBooking = []byte{8}
-	LedgerStateReality               = []byte{9}
-	LedgerStateConflictSet           = []byte{10}
+	ValueTangleTransferMetadata = []byte{5}
+	ValueTangleConsumers        = []byte{6}
+	ValueTangleMissingTransfers = []byte{7}
+
+	LedgerStateTransferOutput        = []byte{8}
+	LedgerStateTransferOutputBooking = []byte{9}
+	LedgerStateReality               = []byte{10}
+	LedgerStateConflictSet           = []byte{11}
 )
diff --git a/packages/binary/tangle/model/transaction/cached_transaction.go b/packages/binary/tangle/model/transaction/cached_transaction.go
index 5f177ea7..d95494ed 100644
--- a/packages/binary/tangle/model/transaction/cached_transaction.go
+++ b/packages/binary/tangle/model/transaction/cached_transaction.go
@@ -12,7 +12,7 @@ func (cachedTransaction *CachedTransaction) Retain() *CachedTransaction {
 	return &CachedTransaction{cachedTransaction.CachedObject.Retain()}
 }
 
-func (cachedTransaction *CachedTransaction) Consume(consumer func(object *Transaction)) bool {
+func (cachedTransaction *CachedTransaction) Consume(consumer func(transaction *Transaction)) bool {
 	return cachedTransaction.CachedObject.Consume(func(object objectstorage.StorableObject) {
 		consumer(object.(*Transaction))
 	})
diff --git a/packages/binary/tangle/tipselector/events.go b/packages/binary/tangle/tipselector/events.go
new file mode 100644
index 00000000..563e4a70
--- /dev/null
+++ b/packages/binary/tangle/tipselector/events.go
@@ -0,0 +1,15 @@
+package tipselector
+
+import (
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/hive.go/events"
+)
+
+type Events struct {
+	TipAdded   *events.Event
+	TipRemoved *events.Event
+}
+
+func transactionIdEvent(handler interface{}, params ...interface{}) {
+	handler.(func(transaction.Id))(params[0].(transaction.Id))
+}
diff --git a/packages/binary/tangle/tipselector/tipselector.go b/packages/binary/tangle/tipselector/tipselector.go
new file mode 100644
index 00000000..1b03500c
--- /dev/null
+++ b/packages/binary/tangle/tipselector/tipselector.go
@@ -0,0 +1,68 @@
+package tipselector
+
+import (
+	"github.com/iotaledger/goshimmer/packages/binary/datastructure"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/hive.go/events"
+)
+
+type TipSelector struct {
+	tips   *datastructure.RandomMap
+	Events Events
+}
+
+func New() *TipSelector {
+	return &TipSelector{
+		tips: datastructure.NewRandomMap(),
+		Events: Events{
+			TipAdded:   events.NewEvent(transactionIdEvent),
+			TipRemoved: events.NewEvent(transactionIdEvent),
+		},
+	}
+}
+
+func (tipSelector *TipSelector) AddTip(transaction *transaction.Transaction) {
+	transactionId := transaction.GetId()
+	if tipSelector.tips.Set(transactionId, transactionId) {
+		tipSelector.Events.TipAdded.Trigger(transactionId)
+	}
+
+	trunkTransactionId := transaction.GetTrunkTransactionId()
+	if _, deleted := tipSelector.tips.Delete(trunkTransactionId); deleted {
+		tipSelector.Events.TipRemoved.Trigger(trunkTransactionId)
+	}
+
+	branchTransactionId := transaction.GetBranchTransactionId()
+	if _, deleted := tipSelector.tips.Delete(branchTransactionId); deleted {
+		tipSelector.Events.TipRemoved.Trigger(branchTransactionId)
+	}
+}
+
+func (tipSelector *TipSelector) GetTips() (trunkTransaction, branchTransaction transaction.Id) {
+	tip := tipSelector.tips.RandomEntry()
+	if tip == nil {
+		trunkTransaction = transaction.EmptyId
+		branchTransaction = transaction.EmptyId
+
+		return
+	}
+
+	branchTransaction = tip.(transaction.Id)
+
+	if tipSelector.tips.Size() == 1 {
+		trunkTransaction = branchTransaction
+
+		return
+	}
+
+	trunkTransaction = tipSelector.tips.RandomEntry().(transaction.Id)
+	for trunkTransaction == branchTransaction && tipSelector.tips.Size() > 1 {
+		trunkTransaction = tipSelector.tips.RandomEntry().(transaction.Id)
+	}
+
+	return
+}
+
+func (tipSelector *TipSelector) GetTipCount() int {
+	return tipSelector.tips.Size()
+}
diff --git a/packages/binary/tangle/tipselector/tipselector_test.go b/packages/binary/tangle/tipselector/tipselector_test.go
new file mode 100644
index 00000000..0bd3d385
--- /dev/null
+++ b/packages/binary/tangle/tipselector/tipselector_test.go
@@ -0,0 +1,51 @@
+package tipselector
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/iotaledger/goshimmer/packages/binary/identity"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload/data"
+)
+
+func Test(t *testing.T) {
+	// create tip selector
+	tipSelector := New()
+
+	// check if first tips point to genesis
+	trunk1, branch1 := tipSelector.GetTips()
+	assert.Equal(t, transaction.EmptyId, trunk1)
+	assert.Equal(t, transaction.EmptyId, branch1)
+
+	// create a transaction and attach it
+	transaction1 := transaction.New(trunk1, branch1, identity.Generate(), data.New([]byte("testtransaction")))
+	tipSelector.AddTip(transaction1)
+
+	// check if the tip shows up in the tip count
+	assert.Equal(t, 1, tipSelector.GetTipCount())
+
+	// check if next tips point to our first transaction
+	trunk2, branch2 := tipSelector.GetTips()
+	assert.Equal(t, transaction1.GetId(), trunk2)
+	assert.Equal(t, transaction1.GetId(), branch2)
+
+	// create a 2nd transaction and attach it
+	transaction2 := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("testtransaction")))
+	tipSelector.AddTip(transaction2)
+
+	// check if the tip shows up in the tip count
+	assert.Equal(t, 2, tipSelector.GetTipCount())
+
+	// attach a transaction to our two tips
+	trunk3, branch3 := tipSelector.GetTips()
+	transaction3 := transaction.New(trunk3, branch3, identity.Generate(), data.New([]byte("testtransaction")))
+	tipSelector.AddTip(transaction3)
+
+	// check if the tip shows replaces the current tips
+	trunk4, branch4 := tipSelector.GetTips()
+	assert.Equal(t, 1, tipSelector.GetTipCount())
+	assert.Equal(t, transaction3.GetId(), trunk4)
+	assert.Equal(t, transaction3.GetId(), branch4)
+}
diff --git a/packages/gossip/manager.go b/packages/gossip/manager.go
index 49a9d0d9..e28c81af 100644
--- a/packages/gossip/manager.go
+++ b/packages/gossip/manager.go
@@ -6,6 +6,8 @@ import (
 	"net"
 	"sync"
 
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+
 	"github.com/golang/protobuf/proto"
 	pb "github.com/iotaledger/goshimmer/packages/gossip/proto"
 	"github.com/iotaledger/goshimmer/packages/gossip/server"
@@ -24,7 +26,7 @@ var (
 )
 
 // GetTransaction defines a function that returns the transaction data with the given hash.
-type GetTransaction func(txHash []byte) ([]byte, error)
+type GetTransaction func(transactionId transaction.Id) ([]byte, error)
 
 type Manager struct {
 	local          *peer.Local
@@ -254,7 +256,7 @@ 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(msg.GetHash())
+		tx, err := m.getTransaction(transaction.NewId(msg.GetHash()))
 		if err != nil {
 			m.log.Debugw("error getting transaction", "hash", msg.GetHash(), "err", err)
 		} else {
diff --git a/plugins/bundleprocessor/bundleprocessor.go b/plugins/bundleprocessor/bundleprocessor.go
deleted file mode 100644
index 6085e2a9..00000000
--- a/plugins/bundleprocessor/bundleprocessor.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package bundleprocessor
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/iotaledger/goshimmer/packages/model/bundle"
-	"github.com/iotaledger/goshimmer/packages/model/transactionmetadata"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/hive.go/workerpool"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-var workerPool = workerpool.New(func(task workerpool.Task) {
-	if err := ProcessSolidBundleHead(task.Param(0).(*value_transaction.ValueTransaction)); err != nil {
-		Events.Error.Trigger(err)
-	}
-
-	task.Return(nil)
-}, workerpool.WorkerCount(WORKER_COUNT), workerpool.QueueSize(2*WORKER_COUNT))
-
-var WORKER_COUNT = runtime.NumCPU()
-
-func ProcessSolidBundleHead(headTransaction *value_transaction.ValueTransaction) error {
-	// only process the bundle if we didn't process it, yet
-	_, err := tangle.GetBundle(headTransaction.GetHash(), func(headTransactionHash trinary.Trytes) (*bundle.Bundle, error) {
-		// abort if bundle syntax is wrong
-		if !headTransaction.IsHead() {
-			return nil, fmt.Errorf("%w: transaction needs to be the head of the bundle", ErrProcessBundleFailed)
-		}
-
-		// initialize event variables
-		newBundle := bundle.New(headTransactionHash)
-		bundleTransactions := make([]*value_transaction.ValueTransaction, 0)
-
-		// iterate through trunk transactions until we reach the tail
-		currentTransaction := headTransaction
-		for {
-			// abort if we reached a previous head
-			if currentTransaction.IsHead() && currentTransaction != headTransaction {
-				newBundle.SetTransactionHashes(mapTransactionsToTransactionHashes(bundleTransactions))
-
-				Events.InvalidBundle.Trigger(newBundle, bundleTransactions)
-				return nil, fmt.Errorf("%w: missing bundle tail", ErrProcessBundleFailed)
-			}
-
-			// update bundle transactions
-			bundleTransactions = append(bundleTransactions, currentTransaction)
-
-			// retrieve & update metadata
-			currentTransactionMetadata, err := tangle.GetTransactionMetadata(currentTransaction.GetHash(), transactionmetadata.New)
-			if err != nil {
-				return nil, fmt.Errorf("%w: failed to retrieve transaction metadata: %s", ErrProcessBundleFailed, err)
-			}
-			currentTransactionMetadata.SetBundleHeadHash(headTransactionHash)
-
-			// update value bundle flag
-			if !newBundle.IsValueBundle() && currentTransaction.GetValue() < 0 {
-				newBundle.SetValueBundle(true)
-			}
-
-			// if we are done -> trigger events
-			if currentTransaction.IsTail() {
-				newBundle.SetTransactionHashes(mapTransactionsToTransactionHashes(bundleTransactions))
-
-				if newBundle.IsValueBundle() {
-					valueBundleProcessorWorkerPool.Submit(newBundle, bundleTransactions)
-
-					return newBundle, nil
-				}
-
-				Events.BundleSolid.Trigger(newBundle, bundleTransactions)
-
-				return newBundle, nil
-			}
-
-			// try to iterate to next turn
-			if nextTransaction, err := tangle.GetTransaction(currentTransaction.GetTrunkTransactionHash()); err != nil {
-				return nil, fmt.Errorf("%w: failed to retrieve trunk while processing bundle: %s", ErrProcessBundleFailed, err)
-			} else if nextTransaction == nil {
-				err := fmt.Errorf("%w: failed to retrieve trunk while processing bundle: missing trunk transaction %s\n", ErrProcessBundleFailed, currentTransaction.GetTrunkTransactionHash())
-				fmt.Println(err)
-				return nil, err
-			} else {
-				currentTransaction = nextTransaction
-			}
-		}
-	})
-
-	return err
-}
-
-func mapTransactionsToTransactionHashes(transactions []*value_transaction.ValueTransaction) (result []trinary.Trytes) {
-	result = make([]trinary.Trytes, len(transactions))
-	for k, v := range transactions {
-		result[k] = v.GetHash()
-	}
-
-	return
-}
diff --git a/plugins/bundleprocessor/bundleprocessor_test.go b/plugins/bundleprocessor/bundleprocessor_test.go
deleted file mode 100644
index e7b90366..00000000
--- a/plugins/bundleprocessor/bundleprocessor_test.go
+++ /dev/null
@@ -1,143 +0,0 @@
-package bundleprocessor
-
-import (
-	"io/ioutil"
-	"os"
-	"sync"
-	"testing"
-
-	"github.com/iotaledger/goshimmer/packages/client"
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/model/bundle"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/packages/parameter"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/goshimmer/plugins/tipselection"
-	"github.com/iotaledger/hive.go/events"
-	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/node"
-	"github.com/iotaledger/iota.go/consts"
-	"github.com/magiconair/properties/assert"
-	"github.com/spf13/viper"
-	"github.com/stretchr/testify/require"
-)
-
-var seed = client.NewSeed("YFHQWAUPCXC9S9DSHP9NDF9RLNPMZVCMSJKUKQP9SWUSUCPRQXCMDVDVZ9SHHESHIQNCXWBJF9UJSWE9Z", consts.SecurityLevelMedium)
-
-func init() {
-	err := parameter.LoadDefaultConfig(false)
-	if err != nil {
-		log.Fatalf("Failed to initialize config: %s", err)
-	}
-	logger.InitGlobalLogger(&viper.Viper{})
-}
-
-func BenchmarkValidateSignatures(b *testing.B) {
-	bundleFactory := client.NewBundleFactory()
-	bundleFactory.AddInput(seed.GetAddress(0), -400)
-	bundleFactory.AddOutput(seed.GetAddress(1), 400, "Testmessage")
-	bundleFactory.AddOutput(client.NewAddress("SJKUKQP9SWUSUCPRQXCMDVDVZ9SHHESHIQNCXWBJF9UJSWE9ZYFHQWAUPCXC9S9DSHP9NDF9RLNPMZVCM"), 400, "Testmessage")
-
-	generatedBundle := bundleFactory.GenerateBundle(tipselection.GetRandomTip(), tipselection.GetRandomTip())
-
-	b.ResetTimer()
-
-	var wg sync.WaitGroup
-
-	for i := 0; i < b.N; i++ {
-		wg.Add(1)
-
-		go func() {
-			ValidateSignatures(generatedBundle.GetEssenceHash(), generatedBundle.GetTransactions())
-
-			wg.Done()
-		}()
-	}
-
-	wg.Wait()
-}
-
-func TestValidateSignatures(t *testing.T) {
-	bundleFactory := client.NewBundleFactory()
-	bundleFactory.AddInput(seed.GetAddress(0), -400)
-	bundleFactory.AddOutput(seed.GetAddress(1), 400, "Testmessage")
-	bundleFactory.AddOutput(client.NewAddress("SJKUKQP9SWUSUCPRQXCMDVDVZ9SHHESHIQNCXWBJF9UJSWE9ZYFHQWAUPCXC9S9DSHP9NDF9RLNPMZVCM"), 400, "Testmessage")
-
-	generatedBundle := bundleFactory.GenerateBundle(tipselection.GetRandomTip(), tipselection.GetRandomTip())
-
-	successful, err := ValidateSignatures(generatedBundle.GetEssenceHash(), generatedBundle.GetTransactions())
-	if err != nil {
-		t.Error(err)
-	}
-	assert.Equal(t, successful, true, "validation failed")
-}
-
-func TestProcessSolidBundleHead(t *testing.T) {
-	dir, err := ioutil.TempDir("", t.Name())
-	require.NoError(t, err)
-	defer os.Remove(dir)
-	// use the tempdir for the database
-	parameter.NodeConfig.Set(database.CFG_DIRECTORY, dir)
-
-	// start a test node
-	node.Start(node.Plugins(tangle.PLUGIN, PLUGIN))
-	defer node.Shutdown()
-
-	t.Run("data", func(t *testing.T) {
-		bundleFactory := client.NewBundleFactory()
-		bundleFactory.AddOutput(seed.GetAddress(1), 400, "Testmessage")
-		bundleFactory.AddOutput(client.NewAddress("SJKUKQP9SWUSUCPRQXCMDVDVZ9SHHESHIQNCXWBJF9UJSWE9ZYFHQWAUPCXC9S9DSHP9NDF9RLNPMZVCM"), 400, "Testmessage")
-
-		generatedBundle := bundleFactory.GenerateBundle(tipselection.GetRandomTip(), tipselection.GetRandomTip())
-		for _, transaction := range generatedBundle.GetTransactions() {
-			tangle.StoreTransaction(transaction)
-		}
-
-		var wg sync.WaitGroup
-		testResults := events.NewClosure(func(bundle *bundle.Bundle, transactions []*value_transaction.ValueTransaction) {
-			assert.Equal(t, bundle.GetHash(), generatedBundle.GetTransactions()[0].GetHash(), "invalid bundle hash")
-			assert.Equal(t, bundle.IsValueBundle(), false, "invalid value bundle status")
-
-			wg.Done()
-		})
-		Events.BundleSolid.Attach(testResults)
-		defer Events.BundleSolid.Detach(testResults)
-
-		wg.Add(1)
-		if err := ProcessSolidBundleHead(generatedBundle.GetTransactions()[0]); err != nil {
-			t.Error(err)
-		}
-
-		wg.Wait()
-	})
-
-	t.Run("value", func(t *testing.T) {
-		bundleFactory := client.NewBundleFactory()
-		bundleFactory.AddInput(seed.GetAddress(0), -400)
-		bundleFactory.AddOutput(seed.GetAddress(1), 400, "Testmessage")
-		bundleFactory.AddOutput(client.NewAddress("SJKUKQP9SWUSUCPRQXCMDVDVZ9SHHESHIQNCXWBJF9UJSWE9ZYFHQWAUPCXC9S9DSHP9NDF9RLNPMZVCM"), 400, "Testmessage")
-
-		generatedBundle := bundleFactory.GenerateBundle(tipselection.GetRandomTip(), tipselection.GetRandomTip())
-		for _, transaction := range generatedBundle.GetTransactions() {
-			tangle.StoreTransaction(transaction)
-		}
-
-		var wg sync.WaitGroup
-		testResults := events.NewClosure(func(bundle *bundle.Bundle, transactions []*value_transaction.ValueTransaction) {
-			assert.Equal(t, bundle.GetHash(), generatedBundle.GetTransactions()[0].GetHash(), "invalid bundle hash")
-			assert.Equal(t, bundle.IsValueBundle(), true, "invalid value bundle status")
-
-			wg.Done()
-		})
-
-		wg.Add(1)
-		Events.BundleSolid.Attach(testResults)
-		defer Events.BundleSolid.Detach(testResults)
-
-		if err := ProcessSolidBundleHead(generatedBundle.GetTransactions()[0]); err != nil {
-			t.Error(err)
-		}
-
-		wg.Wait()
-	})
-}
diff --git a/plugins/bundleprocessor/errors.go b/plugins/bundleprocessor/errors.go
deleted file mode 100644
index 7b488de1..00000000
--- a/plugins/bundleprocessor/errors.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package bundleprocessor
-
-import "errors"
-
-var (
-	ErrProcessBundleFailed = errors.New("failed to process bundle")
-)
diff --git a/plugins/bundleprocessor/events.go b/plugins/bundleprocessor/events.go
deleted file mode 100644
index 46eeaa5c..00000000
--- a/plugins/bundleprocessor/events.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package bundleprocessor
-
-import (
-	"github.com/iotaledger/goshimmer/packages/model/bundle"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/hive.go/events"
-)
-
-var Events = pluginEvents{
-	Error:         events.NewEvent(errorCaller),
-	BundleSolid:   events.NewEvent(bundleEventCaller),
-	InvalidBundle: events.NewEvent(bundleEventCaller),
-}
-
-type pluginEvents struct {
-	Error         *events.Event
-	BundleSolid   *events.Event
-	InvalidBundle *events.Event
-}
-
-func errorCaller(handler interface{}, params ...interface{}) {
-	handler.(func(error))(params[0].(error))
-}
-
-func bundleEventCaller(handler interface{}, params ...interface{}) {
-	handler.(func(*bundle.Bundle, []*value_transaction.ValueTransaction))(params[0].(*bundle.Bundle), params[1].([]*value_transaction.ValueTransaction))
-}
diff --git a/plugins/bundleprocessor/plugin.go b/plugins/bundleprocessor/plugin.go
deleted file mode 100644
index d8a6303d..00000000
--- a/plugins/bundleprocessor/plugin.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package bundleprocessor
-
-import (
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/packages/shutdown"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/hive.go/daemon"
-	"github.com/iotaledger/hive.go/events"
-	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/node"
-)
-
-var PLUGIN = node.NewPlugin("Bundle Processor", node.Enabled, configure, run)
-var log *logger.Logger
-
-func configure(*node.Plugin) {
-	log = logger.NewLogger("Bundle Processor")
-
-	tangle.Events.TransactionSolid.Attach(events.NewClosure(func(tx *value_transaction.ValueTransaction) {
-		if tx.IsHead() {
-			workerPool.Submit(tx)
-		}
-	}))
-
-	Events.Error.Attach(events.NewClosure(func(err error) {
-		log.Error(err)
-	}))
-}
-
-func run(*node.Plugin) {
-	log.Info("Starting Bundle Processor ...")
-
-	daemon.BackgroundWorker("Bundle Processor", func(shutdownSignal <-chan struct{}) {
-		log.Info("Starting Bundle Processor ... done")
-		workerPool.Start()
-		<-shutdownSignal
-		log.Info("Stopping Bundle Processor ...")
-		workerPool.StopAndWait()
-		log.Info("Stopping Bundle Processor ... done")
-	}, shutdown.ShutdownPriorityBundleProcessor)
-
-	log.Info("Starting Value Bundle Processor ...")
-
-	daemon.BackgroundWorker("Value Bundle Processor", func(shutdownSignal <-chan struct{}) {
-		log.Info("Starting Value Bundle Processor ... done")
-		valueBundleProcessorWorkerPool.Start()
-		<-shutdownSignal
-		log.Info("Stopping Value Bundle Processor ...")
-		valueBundleProcessorWorkerPool.StopAndWait()
-		log.Info("Stopping Value Bundle Processor ... done")
-	}, shutdown.ShutdownPriorityBundleProcessor)
-}
diff --git a/plugins/bundleprocessor/valuebundleprocessor.go b/plugins/bundleprocessor/valuebundleprocessor.go
deleted file mode 100644
index 984c2b24..00000000
--- a/plugins/bundleprocessor/valuebundleprocessor.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package bundleprocessor
-
-import (
-	"github.com/iotaledger/goshimmer/packages/model/bundle"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/hive.go/workerpool"
-	"github.com/iotaledger/iota.go/curl"
-	"github.com/iotaledger/iota.go/signing"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-var valueBundleProcessorWorkerPool = workerpool.New(func(task workerpool.Task) {
-	if err := ProcessSolidValueBundle(task.Param(0).(*bundle.Bundle), task.Param(1).([]*value_transaction.ValueTransaction)); err != nil {
-		Events.Error.Trigger(err)
-	}
-
-	task.Return(nil)
-}, workerpool.WorkerCount(WORKER_COUNT), workerpool.QueueSize(2*WORKER_COUNT))
-
-func ProcessSolidValueBundle(bundle *bundle.Bundle, bundleTransactions []*value_transaction.ValueTransaction) error {
-	bundle.SetBundleEssenceHash(CalculateBundleHash(bundleTransactions))
-
-	Events.BundleSolid.Trigger(bundle, bundleTransactions)
-
-	return nil
-}
-
-func CalculateBundleHash(transactions []*value_transaction.ValueTransaction) trinary.Trytes {
-	var lastInputAddress trinary.Trytes
-
-	var concatenatedBundleEssences = make(trinary.Trits, len(transactions)*value_transaction.BUNDLE_ESSENCE_SIZE)
-	for i, bundleTransaction := range transactions {
-		if bundleTransaction.GetValue() <= 0 {
-			lastInputAddress = bundleTransaction.GetAddress()
-		}
-
-		copy(concatenatedBundleEssences[value_transaction.BUNDLE_ESSENCE_SIZE*i:value_transaction.BUNDLE_ESSENCE_SIZE*(i+1)], bundleTransaction.GetBundleEssence(lastInputAddress != bundleTransaction.GetAddress()))
-	}
-
-	bundleHash, err := curl.HashTrits(concatenatedBundleEssences)
-	if err != nil {
-		panic(err)
-	}
-	return trinary.MustTritsToTrytes(bundleHash)
-}
-
-func ValidateSignatures(bundleHash trinary.Hash, txs []*value_transaction.ValueTransaction) (bool, error) {
-	for i, tx := range txs {
-		// ignore all non-input transactions
-		if tx.GetValue() >= 0 {
-			continue
-		}
-
-		address := tx.GetAddress()
-
-		// it is unknown how many fragments there will be
-		fragments := []trinary.Trytes{tx.GetSignatureMessageFragment()}
-
-		// each consecutive meta transaction with the same address contains another signature fragment
-		for j := i; j < len(txs)-1; j++ {
-			otherTx := txs[j+1]
-			if otherTx.GetValue() != 0 || otherTx.GetAddress() != address {
-				break
-			}
-
-			fragments = append(fragments, otherTx.GetSignatureMessageFragment())
-		}
-
-		// validate all the fragments against the address using Kerl
-		valid, err := signing.ValidateSignatures(address, fragments, bundleHash)
-		if err != nil {
-			return false, err
-		}
-		if !valid {
-			return false, nil
-		}
-	}
-
-	return true, nil
-}
diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go
index 0293370e..57f348d1 100644
--- a/plugins/gossip/gossip.go
+++ b/plugins/gossip/gossip.go
@@ -6,17 +6,17 @@ import (
 	"strconv"
 	"sync"
 
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/plugins/tangle"
+
 	gp "github.com/iotaledger/goshimmer/packages/gossip"
 	"github.com/iotaledger/goshimmer/packages/gossip/server"
 	"github.com/iotaledger/goshimmer/packages/parameter"
 	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
 	"github.com/iotaledger/goshimmer/plugins/cli"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
 	"github.com/iotaledger/hive.go/autopeering/peer"
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
 	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
 )
 
 var (
@@ -105,24 +105,16 @@ func checkConnection(srv *server.TCP, self *peer.Peer) {
 	wg.Wait()
 }
 
-func getTransaction(hash []byte) ([]byte, error) {
-	tx, err := tangle.GetTransaction(typeutils.BytesToString(hash))
-	log.Debugw("get tx from db",
-		"hash", hash,
-		"tx", tx,
-		"err", err,
-	)
-	if err != nil {
-		return nil, fmt.Errorf("could not get transaction: %w", err)
-	}
-	if tx == nil {
-		return nil, fmt.Errorf("transaction not found: hash=%s", hash)
+func getTransaction(transactionId transaction.Id) (bytes []byte, err error) {
+	log.Debugw("get tx from db", "id", transactionId.String())
+
+	if !tangle.Instance.GetTransaction(transactionId).Consume(func(transaction *transaction.Transaction) {
+		bytes = transaction.GetBytes()
+	}) {
+		err = fmt.Errorf("transaction not found: hash=%s", transactionId)
 	}
-	return tx.GetBytes(), nil
-}
 
-func requestTransaction(hash trinary.Hash) {
-	mgr.RequestTransaction(typeutils.StringToBytes(hash))
+	return
 }
 
 func GetAllNeighbors() []*gp.Neighbor {
diff --git a/plugins/gossip/plugin.go b/plugins/gossip/plugin.go
index ff4b335f..66a27e22 100644
--- a/plugins/gossip/plugin.go
+++ b/plugins/gossip/plugin.go
@@ -1,8 +1,9 @@
 package gossip
 
 import (
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transactionmetadata"
 	"github.com/iotaledger/goshimmer/packages/gossip"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
 	"github.com/iotaledger/goshimmer/packages/shutdown"
 	"github.com/iotaledger/goshimmer/plugins/tangle"
 	"github.com/iotaledger/hive.go/autopeering/peer"
@@ -69,9 +70,22 @@ func configureEvents() {
 		log.Infof("Neighbor removed: %s / %s", gossip.GetAddress(p), p.ID())
 	}))
 
-	// gossip transactions on solidification
-	tangle.Events.TransactionSolid.Attach(events.NewClosure(func(tx *value_transaction.ValueTransaction) {
-		mgr.SendTransaction(tx.GetBytes())
+	// configure flow of incoming transactions
+	gossip.Events.TransactionReceived.Attach(events.NewClosure(func(event *gossip.TransactionReceivedEvent) {
+		tangle.TransactionParser.Parse(event.Data)
+	}))
+
+	// configure flow of outgoing transactions (gossip on solidification)
+	tangle.Instance.Events.TransactionSolid.Attach(events.NewClosure(func(cachedTransaction *transaction.CachedTransaction, transactionMetadata *transactionmetadata.CachedTransactionMetadata) {
+		transactionMetadata.Release()
+
+		cachedTransaction.Consume(func(transaction *transaction.Transaction) {
+			mgr.SendTransaction(transaction.GetBytes())
+		})
+	}))
+
+	// request missing transactions
+	tangle.TransactionRequester.Events.SendRequest.Attach(events.NewClosure(func(transactionId transaction.Id) {
+		mgr.RequestTransaction(transactionId[:])
 	}))
-	tangle.SetRequester(tangle.RequesterFunc(requestTransaction))
 }
diff --git a/plugins/graph/plugin.go b/plugins/graph/plugin.go
index af586165..566ba82a 100644
--- a/plugins/graph/plugin.go
+++ b/plugins/graph/plugin.go
@@ -8,7 +8,7 @@ import (
 	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
 	"github.com/iotaledger/goshimmer/packages/parameter"
 	"github.com/iotaledger/goshimmer/packages/shutdown"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
+	"github.com/iotaledger/goshimmer/plugins/tangle_old"
 	"golang.org/x/net/context"
 
 	engineio "github.com/googollee/go-engine.io"
@@ -100,10 +100,10 @@ func run(*node.Plugin) {
 
 	daemon.BackgroundWorker("Graph[NewTxWorker]", func(shutdownSignal <-chan struct{}) {
 		log.Info("Starting Graph[NewTxWorker] ... done")
-		tangle.Events.TransactionStored.Attach(notifyNewTx)
+		tangle_old.Events.TransactionStored.Attach(notifyNewTx)
 		newTxWorkerPool.Start()
 		<-shutdownSignal
-		tangle.Events.TransactionStored.Detach(notifyNewTx)
+		tangle_old.Events.TransactionStored.Detach(notifyNewTx)
 		newTxWorkerPool.Stop()
 		log.Info("Stopping Graph[NewTxWorker] ... done")
 	}, shutdown.ShutdownPriorityGraph)
diff --git a/plugins/spa/explorer_routes.go b/plugins/spa/explorer_routes.go
index 7d324e14..13d45105 100644
--- a/plugins/spa/explorer_routes.go
+++ b/plugins/spa/explorer_routes.go
@@ -4,9 +4,11 @@ import (
 	"net/http"
 	"sync"
 
-	"github.com/iotaledger/goshimmer/packages/model/transactionmetadata"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
 	"github.com/iotaledger/goshimmer/plugins/tangle"
+
+	"github.com/iotaledger/goshimmer/packages/model/transactionmetadata"
+	"github.com/iotaledger/goshimmer/plugins/tangle_old"
 	"github.com/labstack/echo"
 	"github.com/pkg/errors"
 
@@ -16,26 +18,23 @@ import (
 )
 
 type ExplorerTx struct {
-	Hash                     Hash   `json:"hash"`
-	SignatureMessageFragment Trytes `json:"signature_message_fragment"`
-	Address                  Hash   `json:"address"`
-	Value                    int64  `json:"value"`
-	Timestamp                uint   `json:"timestamp"`
-	Trunk                    Hash   `json:"trunk"`
-	Branch                   Hash   `json:"branch"`
-	Solid                    bool   `json:"solid"`
-	MWM                      int    `json:"mwm"`
+	Hash                     transaction.Id `json:"hash"`
+	SignatureMessageFragment Trytes         `json:"signature_message_fragment"`
+	Timestamp                uint           `json:"timestamp"`
+	Trunk                    transaction.Id `json:"trunk"`
+	Branch                   transaction.Id `json:"branch"`
+	Solid                    bool           `json:"solid"`
+	MWM                      int            `json:"mwm"`
 }
 
-func createExplorerTx(hash Hash, tx *value_transaction.ValueTransaction) (*ExplorerTx, error) {
-
-	txMetadata, err := tangle.GetTransactionMetadata(hash, transactionmetadata.New)
+func createExplorerTx(tx *transaction.Transaction) (*ExplorerTx, error) {
+	txMetadata, err := tangle_old.GetTransactionMetadata(hash, transactionmetadata.New)
 	if err != nil {
 		return nil, err
 	}
 
 	t := &ExplorerTx{
-		Hash:                     tx.GetHash(),
+		Hash:                     tx.GetId(),
 		SignatureMessageFragment: tx.GetSignatureMessageFragment(),
 		Address:                  tx.GetAddress(),
 		Timestamp:                tx.GetTimestamp(),
@@ -121,20 +120,13 @@ func setupExplorerRoutes(routeGroup *echo.Group) {
 	})
 }
 
-func findTransaction(hash Hash) (*ExplorerTx, error) {
-	if !guards.IsTrytesOfExactLength(hash, consts.HashTrytesSize) {
-		return nil, errors.Wrapf(ErrInvalidParameter, "hash invalid: %s", hash)
-	}
-
-	tx, err := tangle.GetTransaction(hash)
-	if err != nil {
-		return nil, err
-	}
-	if tx == nil {
-		return nil, errors.Wrapf(ErrNotFound, "tx hash: %s", hash)
+func findTransaction(transactionId transaction.Id) (*ExplorerTx, error) {
+	if !tangle.Instance.GetTransaction(transactionId).Consume(func(transaction *transaction.Transaction) {
+		t, err := createExplorerTx(transaction)
+	}) {
+		return nil, errors.Wrapf(ErrNotFound, "tx hash: %s", transactionId.String())
 	}
 
-	t, err := createExplorerTx(hash, tx)
 	return t, err
 }
 
@@ -146,7 +138,7 @@ func findAddress(hash Hash) (*ExplorerAdress, error) {
 		return nil, errors.Wrapf(ErrInvalidParameter, "hash invalid: %s", hash)
 	}
 
-	txHashes, err := tangle.ReadTransactionHashesForAddressFromDatabase(hash)
+	txHashes, err := tangle_old.ReadTransactionHashesForAddressFromDatabase(hash)
 	if err != nil {
 		return nil, ErrInternalError
 	}
@@ -159,7 +151,7 @@ func findAddress(hash Hash) (*ExplorerAdress, error) {
 	for i := 0; i < len(txHashes); i++ {
 		txHash := txHashes[i]
 
-		tx, err := tangle.GetTransaction(hash)
+		tx, err := tangle_old.GetTransaction(hash)
 		if err != nil {
 			continue
 		}
diff --git a/plugins/tangle/approvers.go b/plugins/tangle/approvers.go
deleted file mode 100644
index 3e50c29c..00000000
--- a/plugins/tangle/approvers.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package tangle
-
-import (
-	"fmt"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/model/approvers"
-	"github.com/iotaledger/hive.go/lru_cache"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region global public api ////////////////////////////////////////////////////////////////////////////////////////////
-
-// GetApprovers retrieves approvers from the database.
-func GetApprovers(transactionHash trinary.Trytes, computeIfAbsent ...func(trinary.Trytes) *approvers.Approvers) (result *approvers.Approvers, err error) {
-	if cacheResult := approversCache.ComputeIfAbsent(transactionHash, func() interface{} {
-		if dbApprovers, dbErr := getApproversFromDatabase(transactionHash); dbErr != nil {
-			err = dbErr
-
-			return nil
-		} else if dbApprovers != nil {
-			return dbApprovers
-		} else {
-			if len(computeIfAbsent) >= 1 {
-				return computeIfAbsent[0](transactionHash)
-			}
-
-			return nil
-		}
-	}); cacheResult != nil && cacheResult.(*approvers.Approvers) != nil {
-		result = cacheResult.(*approvers.Approvers)
-	}
-
-	return
-}
-
-func ContainsApprovers(transactionHash trinary.Trytes) (result bool, err error) {
-	if approversCache.Contains(transactionHash) {
-		result = true
-	} else {
-		result, err = databaseContainsApprovers(transactionHash)
-	}
-
-	return
-}
-
-func StoreApprovers(approvers *approvers.Approvers) {
-	approversCache.Set(approvers.GetHash(), approvers)
-}
-
-// region lru cache ////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var approversCache = lru_cache.NewLRUCache(APPROVERS_CACHE_SIZE, &lru_cache.LRUCacheOptions{
-	EvictionCallback:  onEvictApprovers,
-	EvictionBatchSize: 100,
-})
-
-func onEvictApprovers(_ interface{}, values interface{}) {
-	// TODO: replace with apply
-	for _, obj := range values.([]interface{}) {
-		if approvers := obj.(*approvers.Approvers); approvers.GetModified() {
-			if err := storeApproversInDatabase(approvers); err != nil {
-				panic(err)
-			}
-		}
-	}
-}
-
-func FlushApproversCache() {
-	approversCache.DeleteAll()
-}
-
-const (
-	APPROVERS_CACHE_SIZE = 50000
-)
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region database /////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var approversDatabase database.Database
-
-func configureApproversDatabase() {
-	if db, err := database.Get(database.DBPrefixApprovers, database.GetBadgerInstance()); err != nil {
-		panic(err)
-	} else {
-		approversDatabase = db
-	}
-}
-
-func storeApproversInDatabase(approvers *approvers.Approvers) error {
-	if approvers.GetModified() {
-		if err := approversDatabase.Set(database.Entry{Key: typeutils.StringToBytes(approvers.GetHash()), Value: approvers.Marshal()}); err != nil {
-			return fmt.Errorf("%w: failed to store approvers: %s", ErrDatabaseError, err)
-		}
-		approvers.SetModified(false)
-	}
-
-	return nil
-}
-
-func getApproversFromDatabase(transactionHash trinary.Trytes) (*approvers.Approvers, error) {
-	approversData, err := approversDatabase.Get(typeutils.StringToBytes(transactionHash))
-	if err != nil {
-		if err == database.ErrKeyNotFound {
-			return nil, nil
-		}
-		return nil, fmt.Errorf("%w: failed to retrieve approvers: %s", ErrDatabaseError, err)
-	}
-
-	var result approvers.Approvers
-	if err = result.Unmarshal(approversData.Value); err != nil {
-		panic(err)
-	}
-
-	return &result, nil
-}
-
-func databaseContainsApprovers(transactionHash trinary.Trytes) (bool, error) {
-	if contains, err := approversDatabase.Contains(typeutils.StringToBytes(transactionHash)); err != nil {
-		return false, fmt.Errorf("%w: failed to check if the approvers exist: %s", ErrDatabaseError, err)
-	} else {
-		return contains, nil
-	}
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/tangle/bundle.go b/plugins/tangle/bundle.go
deleted file mode 100644
index 2cb1fb89..00000000
--- a/plugins/tangle/bundle.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package tangle
-
-import (
-	"fmt"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/model/bundle"
-	"github.com/iotaledger/hive.go/lru_cache"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region global public api ////////////////////////////////////////////////////////////////////////////////////////////
-
-// GetBundle retrieves bundle from the database.
-func GetBundle(headerTransactionHash trinary.Trytes, computeIfAbsent ...func(trinary.Trytes) (*bundle.Bundle, error)) (result *bundle.Bundle, err error) {
-	if cacheResult := bundleCache.ComputeIfAbsent(headerTransactionHash, func() interface{} {
-		if dbBundle, dbErr := getBundleFromDatabase(headerTransactionHash); dbErr != nil {
-			err = dbErr
-
-			return nil
-		} else if dbBundle != nil {
-			return dbBundle
-		} else {
-			if len(computeIfAbsent) >= 1 {
-				if computedBundle, computedErr := computeIfAbsent[0](headerTransactionHash); computedErr != nil {
-					err = computedErr
-				} else {
-					return computedBundle
-				}
-			}
-
-			return nil
-		}
-	}); cacheResult != nil && cacheResult.(*bundle.Bundle) != nil {
-		result = cacheResult.(*bundle.Bundle)
-	}
-
-	return
-}
-
-func ContainsBundle(headerTransactionHash trinary.Trytes) (result bool, err error) {
-	if bundleCache.Contains(headerTransactionHash) {
-		result = true
-	} else {
-		result, err = databaseContainsBundle(headerTransactionHash)
-	}
-
-	return
-}
-
-func StoreBundle(bundle *bundle.Bundle) {
-	bundleCache.Set(bundle.GetHash(), bundle)
-}
-
-// region lru cache ////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var bundleCache = lru_cache.NewLRUCache(BUNDLE_CACHE_SIZE, &lru_cache.LRUCacheOptions{
-	EvictionCallback:  onEvictBundles,
-	EvictionBatchSize: 100,
-})
-
-func onEvictBundles(_ interface{}, values interface{}) {
-	// TODO: replace with apply
-	for _, obj := range values.([]interface{}) {
-		if bndl := obj.(*bundle.Bundle); bndl.GetModified() {
-			if err := storeBundleInDatabase(bndl); err != nil {
-				panic(err)
-			}
-		}
-	}
-}
-
-func FlushBundleCache() {
-	bundleCache.DeleteAll()
-}
-
-const (
-	BUNDLE_CACHE_SIZE = 500
-)
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region database /////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var bundleDatabase database.Database
-
-func configureBundleDatabase() {
-	if db, err := database.Get(database.DBPrefixBundle, database.GetBadgerInstance()); err != nil {
-		panic(err)
-	} else {
-		bundleDatabase = db
-	}
-}
-
-func storeBundleInDatabase(bundle *bundle.Bundle) error {
-	if bundle.GetModified() {
-		if err := bundleDatabase.Set(database.Entry{Key: typeutils.StringToBytes(bundle.GetHash()), Value: bundle.Marshal()}); err != nil {
-			return fmt.Errorf("%w: failed to store bundle: %s", ErrDatabaseError, err)
-		}
-		bundle.SetModified(false)
-	}
-
-	return nil
-}
-
-func getBundleFromDatabase(transactionHash trinary.Trytes) (*bundle.Bundle, error) {
-	bundleData, err := bundleDatabase.Get(typeutils.StringToBytes(transactionHash))
-	if err != nil {
-		if err == database.ErrKeyNotFound {
-			return nil, nil
-		}
-
-		return nil, fmt.Errorf("%w: failed to retrieve bundle: %s", ErrDatabaseError, err)
-	}
-
-	var result bundle.Bundle
-	if err = result.Unmarshal(bundleData.Value); err != nil {
-		panic(err)
-	}
-
-	return &result, nil
-}
-
-func databaseContainsBundle(transactionHash trinary.Trytes) (bool, error) {
-	if contains, err := bundleDatabase.Contains(typeutils.StringToBytes(transactionHash)); err != nil {
-		return false, fmt.Errorf("%w: failed to check if the bundle exists: %s", ErrDatabaseError, err)
-	} else {
-		return contains, nil
-	}
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/tangle/errors.go b/plugins/tangle/errors.go
deleted file mode 100644
index 5ca8797f..00000000
--- a/plugins/tangle/errors.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package tangle
-
-import "errors"
-
-var (
-	ErrDatabaseError = errors.New("database error")
-)
diff --git a/plugins/tangle/events.go b/plugins/tangle/events.go
deleted file mode 100644
index 2a89c724..00000000
--- a/plugins/tangle/events.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package tangle
-
-import (
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/hive.go/events"
-)
-
-var Events = struct {
-	TransactionStored *events.Event
-	TransactionSolid  *events.Event
-}{
-	TransactionStored: events.NewEvent(transactionCaller),
-	TransactionSolid:  events.NewEvent(transactionCaller),
-}
-
-func transactionCaller(handler interface{}, params ...interface{}) {
-	handler.(func(*value_transaction.ValueTransaction))(params[0].(*value_transaction.ValueTransaction))
-}
diff --git a/plugins/tangle/misc.go b/plugins/tangle/misc.go
deleted file mode 100644
index 490f52d7..00000000
--- a/plugins/tangle/misc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package tangle
-
-import (
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-func databaseKeyForHashPrefixedHash(address trinary.Hash, transactionHash trinary.Hash) []byte {
-	//return append(databaseKeyForHashPrefix(address), trinary.MustTrytesToBytes(transactionHash)...)
-	return append(databaseKeyForHashPrefix(address), typeutils.StringToBytes(transactionHash)...)
-}
-
-func databaseKeyForHashPrefix(hash trinary.Hash) []byte {
-	//return trinary.MustTrytesToBytes(hash)
-	return typeutils.StringToBytes(hash)
-}
diff --git a/plugins/tangle/plugin.go b/plugins/tangle/plugin.go
deleted file mode 100644
index 6c6bc090..00000000
--- a/plugins/tangle/plugin.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package tangle
-
-import (
-	"time"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/shutdown"
-	"github.com/iotaledger/hive.go/daemon"
-	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/node"
-	"github.com/iotaledger/hive.go/timeutil"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region plugin module setup //////////////////////////////////////////////////////////////////////////////////////////
-
-var PLUGIN = node.NewPlugin("Tangle", node.Enabled, configure, run)
-var log *logger.Logger
-
-func configure(*node.Plugin) {
-	log = logger.NewLogger("Tangle")
-
-	configureTransactionDatabase()
-	configureTransactionMetaDataDatabase()
-	configureApproversDatabase()
-	configureBundleDatabase()
-	configureTransactionHashesForAddressDatabase()
-	configureSolidifier()
-
-	daemon.BackgroundWorker("Cache Flush", func(shutdownSignal <-chan struct{}) {
-		<-shutdownSignal
-
-		log.Info("Flushing caches to database...")
-		FlushTransactionCache()
-		FlushTransactionMetadata()
-		FlushApproversCache()
-		FlushBundleCache()
-		log.Info("Flushing caches to database... done")
-
-		log.Info("Syncing database to disk...")
-		database.GetBadgerInstance().Close()
-		log.Info("Syncing database to disk... done")
-	}, shutdown.ShutdownPriorityTangle)
-
-}
-
-func run(*node.Plugin) {
-
-	daemon.BackgroundWorker("Badger garbage collection", func(shutdownSignal <-chan struct{}) {
-		timeutil.Ticker(func() {
-			database.CleanupBadgerInstance(log)
-		}, 5*time.Minute, shutdownSignal)
-	}, shutdown.ShutdownPriorityBadgerGarbageCollection)
-
-	runSolidifier()
-}
-
-// Requester provides the functionality to request a transaction from the network.
-type Requester interface {
-	RequestTransaction(hash trinary.Hash)
-}
-
-type RequesterFunc func(hash trinary.Hash)
-
-func (f RequesterFunc) RequestTransaction(hash trinary.Hash) { f(hash) }
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/tangle/solidifier.go b/plugins/tangle/solidifier.go
deleted file mode 100644
index 02d84440..00000000
--- a/plugins/tangle/solidifier.go
+++ /dev/null
@@ -1,265 +0,0 @@
-package tangle
-
-import (
-	"runtime"
-	"time"
-
-	"github.com/iotaledger/goshimmer/packages/gossip"
-	"github.com/iotaledger/goshimmer/packages/model/approvers"
-	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
-	"github.com/iotaledger/goshimmer/packages/model/transactionmetadata"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/packages/shutdown"
-	"github.com/iotaledger/hive.go/daemon"
-	"github.com/iotaledger/hive.go/events"
-	"github.com/iotaledger/hive.go/workerpool"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region plugin module setup //////////////////////////////////////////////////////////////////////////////////////////
-
-const UnsolidInterval = time.Minute
-
-var (
-	workerCount  = runtime.NumCPU()
-	workerPool   *workerpool.WorkerPool
-	requestedTxs *UnsolidTxs
-
-	requester Requester
-)
-
-func SetRequester(req Requester) {
-	requester = req
-}
-
-func configureSolidifier() {
-	workerPool = workerpool.New(func(task workerpool.Task) {
-		processMetaTransaction(task.Param(0).(*meta_transaction.MetaTransaction))
-
-		task.Return(nil)
-	}, workerpool.WorkerCount(workerCount), workerpool.QueueSize(10000))
-
-	requestedTxs = NewUnsolidTxs()
-
-	gossip.Events.TransactionReceived.Attach(events.NewClosure(func(ev *gossip.TransactionReceivedEvent) {
-		metaTx := meta_transaction.FromBytes(ev.Data)
-		if err := metaTx.Validate(); err != nil {
-			log.Warnf("invalid transaction: %s", err)
-			return
-		}
-		workerPool.Submit(metaTx)
-	}))
-}
-
-func runSolidifier() {
-	daemon.BackgroundWorker("Tangle Solidifier", func(shutdownSignal <-chan struct{}) {
-		log.Info("Starting Solidifier ...")
-		workerPool.Start()
-		log.Info("Starting Solidifier ... done")
-
-		<-shutdownSignal
-
-		log.Info("Stopping Solidifier ...")
-		workerPool.StopAndWait()
-		log.Info("Stopping Solidifier ... done")
-	}, shutdown.ShutdownPrioritySolidifier)
-
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-func processMetaTransaction(metaTransaction *meta_transaction.MetaTransaction) {
-	metaTransactionHash := metaTransaction.GetHash()
-
-	var newTransaction bool
-	tx, err := GetTransaction(metaTransactionHash, func(transactionHash trinary.Trytes) *value_transaction.ValueTransaction {
-		newTransaction = true
-
-		tx := value_transaction.FromMetaTransaction(metaTransaction)
-		tx.SetModified(true)
-		return tx
-	})
-	if err != nil {
-		log.Errorf("Unable to process transaction %s: %s", metaTransactionHash, err.Error())
-		return
-	}
-	if newTransaction {
-		log.Debugw("process new transaction", "hash", tx.GetHash())
-		processNewTransaction(tx)
-		requestedTxs.Remove(tx.GetHash())
-		updateRequestedTxs()
-	}
-}
-
-func processNewTransaction(transaction *value_transaction.ValueTransaction) {
-	Events.TransactionStored.Trigger(transaction)
-
-	// store transaction hash for address in DB
-	if err := StoreTransactionHashForAddressInDatabase(
-		&TxHashForAddress{
-			Address: transaction.GetAddress(),
-			TxHash:  transaction.GetHash(),
-		},
-	); err != nil {
-		log.Errorw(err.Error())
-	}
-
-	transactionHash := transaction.GetHash()
-
-	// register tx as approver for trunk
-	if trunkApprovers, err := GetApprovers(transaction.GetTrunkTransactionHash(), approvers.New); err != nil {
-		log.Errorf("Unable to get approvers of transaction %s: %s", transaction.GetTrunkTransactionHash(), err.Error())
-		return
-	} else {
-		trunkApprovers.Add(transactionHash)
-	}
-
-	// register tx as approver for branch
-	if branchApprovers, err := GetApprovers(transaction.GetBranchTransactionHash(), approvers.New); err != nil {
-		log.Errorf("Unable to get approvers of transaction %s: %s", transaction.GetBranchTransactionHash(), err.Error())
-		return
-	} else {
-		branchApprovers.Add(transactionHash)
-	}
-
-	isSolid, err := isSolid(transactionHash)
-	if err != nil {
-		log.Errorf("Unable to check solidity: %s", err.Error())
-	}
-	// if the transaction was solidified propagate this information
-	if isSolid {
-		if err := propagateSolidity(transaction.GetHash()); err != nil {
-			log.Errorf("Unable to propagate solidity: %s", err.Error())
-		}
-	}
-}
-
-// isSolid checks whether the transaction with the given hash is solid. A transaction is solid, if it is
-// either marked as solid or all its referenced transactions are in the database.
-func isSolid(hash trinary.Hash) (bool, error) {
-	// the genesis is always solid
-	if hash == meta_transaction.BRANCH_NULL_HASH {
-		return true, nil
-	}
-	// if the transaction is not in the DB, request it
-	transaction, err := GetTransaction(hash)
-	if err != nil {
-		return false, err
-	}
-	if transaction == nil {
-		if requestedTxs.Add(hash) {
-			requestTransaction(hash)
-		}
-		return false, nil
-	}
-
-	// check whether the transaction is marked solid
-	metadata, err := GetTransactionMetadata(hash, transactionmetadata.New)
-	if err != nil {
-		return false, err
-	}
-	if metadata.GetSolid() {
-		return true, nil
-	}
-
-	branch := contains(transaction.GetBranchTransactionHash())
-	trunk := contains(transaction.GetTrunkTransactionHash())
-
-	if !branch || !trunk {
-		return false, nil
-	}
-	// everything is good, mark the transaction as solid
-	return true, markSolid(transaction)
-}
-
-func contains(hash trinary.Hash) bool {
-	if hash == meta_transaction.BRANCH_NULL_HASH {
-		return true
-	}
-	if contains, _ := ContainsTransaction(hash); !contains {
-		if requestedTxs.Add(hash) {
-			requestTransaction(hash)
-		}
-		return false
-	}
-	return true
-}
-
-func isMarkedSolid(hash trinary.Hash) (bool, error) {
-	if hash == meta_transaction.BRANCH_NULL_HASH {
-		return true, nil
-	}
-	metadata, err := GetTransactionMetadata(hash, transactionmetadata.New)
-	if err != nil {
-		return false, err
-	}
-	return metadata.GetSolid(), nil
-}
-
-func markSolid(transaction *value_transaction.ValueTransaction) error {
-	txMetadata, err := GetTransactionMetadata(transaction.GetHash(), transactionmetadata.New)
-	if err != nil {
-		return err
-	}
-	if txMetadata.SetSolid(true) {
-		log.Debugw("transaction solidified", "hash", transaction.GetHash())
-		Events.TransactionSolid.Trigger(transaction)
-		return propagateSolidity(transaction.GetHash())
-	}
-	return nil
-}
-
-func propagateSolidity(transactionHash trinary.Trytes) error {
-	approvingTransactions, err := GetApprovers(transactionHash, approvers.New)
-	if err != nil {
-		return err
-	}
-	for _, hash := range approvingTransactions.GetHashes() {
-		approver, err := GetTransaction(hash)
-		if err != nil {
-			return err
-		}
-		if approver != nil {
-			branchSolid, err := isMarkedSolid(approver.GetBranchTransactionHash())
-			if err != nil {
-				return err
-			}
-			if !branchSolid {
-				continue
-			}
-			trunkSolid, err := isMarkedSolid(approver.GetTrunkTransactionHash())
-			if err != nil {
-				return err
-			}
-			if !trunkSolid {
-				continue
-			}
-
-			if err := markSolid(approver); err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func updateRequestedTxs() {
-	targetTime := time.Now().Add(-UnsolidInterval)
-	txs := requestedTxs.Update(targetTime)
-	for _, txHash := range txs {
-		if contains, _ := ContainsTransaction(txHash); contains {
-			requestedTxs.Remove(txHash)
-			continue
-		}
-		requestTransaction(txHash)
-	}
-}
-
-func requestTransaction(hash trinary.Trytes) {
-	if requester == nil {
-		return
-	}
-
-	log.Debugw("Requesting tx", "hash", hash)
-	requester.RequestTransaction(hash)
-}
diff --git a/plugins/tangle/solidifier_test.go b/plugins/tangle/solidifier_test.go
deleted file mode 100644
index 28a63bc2..00000000
--- a/plugins/tangle/solidifier_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-package tangle
-
-import (
-	"io/ioutil"
-	stdlog "log"
-	"os"
-	"sync/atomic"
-	"testing"
-	"time"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/gossip"
-	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/packages/parameter"
-	"github.com/iotaledger/hive.go/events"
-	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/node"
-	"github.com/iotaledger/iota.go/trinary"
-	"github.com/stretchr/testify/require"
-)
-
-// use much lower min weight magnitude for the tests
-const testMWM = 8
-
-func init() {
-	if err := parameter.LoadDefaultConfig(false); err != nil {
-		stdlog.Fatalf("Failed to initialize config: %s", err)
-	}
-	if err := logger.InitGlobalLogger(parameter.NodeConfig); err != nil {
-		stdlog.Fatalf("Failed to initialize config: %s", err)
-	}
-}
-
-func TestTangle(t *testing.T) {
-	dir, err := ioutil.TempDir("", t.Name())
-	require.NoError(t, err)
-	defer os.Remove(dir)
-	// use the tempdir for the database
-	parameter.NodeConfig.Set(database.CFG_DIRECTORY, dir)
-
-	// start a test node
-	node.Start(node.Plugins(PLUGIN))
-	defer node.Shutdown()
-
-	t.Run("ReadTransactionHashesForAddressFromDatabase", func(t *testing.T) {
-		tx1 := value_transaction.New()
-		tx1.SetAddress("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
-		tx1.SetTimestamp(uint(time.Now().UnixNano()))
-		require.NoError(t, tx1.DoProofOfWork(testMWM))
-
-		tx2 := value_transaction.New()
-		tx2.SetTimestamp(uint(time.Now().UnixNano()))
-		require.NoError(t, tx2.DoProofOfWork(testMWM))
-
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: tx1.GetBytes()})
-
-		txAddr, err := ReadTransactionHashesForAddressFromDatabase(tx1.GetAddress())
-		require.NoError(t, err)
-		require.ElementsMatch(t, []trinary.Hash{tx1.GetHash()}, txAddr)
-	})
-
-	t.Run("ProofOfWork", func(t *testing.T) {
-		tx1 := value_transaction.New()
-		tx1.SetTimestamp(uint(time.Now().UnixNano()))
-		require.NoError(t, tx1.DoProofOfWork(1))
-
-		tx2 := value_transaction.New()
-		tx2.SetTimestamp(uint(time.Now().UnixNano()))
-		require.NoError(t, tx2.DoProofOfWork(testMWM))
-
-		var counter int32
-		closure := events.NewClosure(func(transaction *value_transaction.ValueTransaction) {
-			atomic.AddInt32(&counter, 1)
-		})
-		Events.TransactionSolid.Attach(closure)
-		defer Events.TransactionSolid.Detach(closure)
-
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: tx1.GetBytes()})
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: tx2.GetBytes()})
-
-		time.Sleep(100 * time.Millisecond)
-		require.EqualValues(t, 1, counter)
-	})
-
-	t.Run("Solidifier", func(t *testing.T) {
-		transaction1 := value_transaction.New()
-		transaction1.SetTimestamp(uint(time.Now().UnixNano()))
-		require.NoError(t, transaction1.DoProofOfWork(testMWM))
-
-		transaction2 := value_transaction.New()
-		transaction2.SetTimestamp(uint(time.Now().UnixNano()))
-		transaction2.SetBranchTransactionHash(transaction1.GetHash())
-		require.NoError(t, transaction2.DoProofOfWork(testMWM))
-
-		transaction3 := value_transaction.New()
-		transaction3.SetTimestamp(uint(time.Now().UnixNano()))
-		transaction3.SetBranchTransactionHash(transaction2.GetHash())
-		require.NoError(t, transaction3.DoProofOfWork(testMWM))
-
-		transaction4 := value_transaction.New()
-		transaction4.SetTimestamp(uint(time.Now().UnixNano()))
-		transaction4.SetBranchTransactionHash(transaction3.GetHash())
-		require.NoError(t, transaction4.DoProofOfWork(testMWM))
-
-		var counter int32
-		closure := events.NewClosure(func(tx *value_transaction.ValueTransaction) {
-			atomic.AddInt32(&counter, 1)
-			log.Infof("Transaction solid: hash=%s", tx.GetHash())
-		})
-		Events.TransactionSolid.Attach(closure)
-		defer Events.TransactionSolid.Detach(closure)
-
-		// only transaction3 should be requested
-		SetRequester(RequesterFunc(func(hash trinary.Hash) {
-			if transaction3.GetHash() == hash {
-				// return the transaction data
-				transactionReceived(&gossip.TransactionReceivedEvent{Data: transaction3.GetBytes()})
-			}
-		}))
-
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: transaction1.GetBytes()})
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: transaction2.GetBytes()})
-		// transactionReceived(&gossip.TransactionReceivedEvent{Data: transaction3.GetBytes()})
-		transactionReceived(&gossip.TransactionReceivedEvent{Data: transaction4.GetBytes()})
-
-		time.Sleep(100 * time.Millisecond)
-		require.EqualValues(t, 4, counter)
-	})
-}
-
-// transactionReceived mocks the TransactionReceived event by allowing lower mwm
-func transactionReceived(ev *gossip.TransactionReceivedEvent) {
-	metaTx := meta_transaction.FromBytes(ev.Data)
-	if metaTx.GetWeightMagnitude() < testMWM {
-		log.Warnf("invalid weight magnitude: %d / %d", metaTx.GetWeightMagnitude(), testMWM)
-		return
-	}
-	processMetaTransaction(metaTx)
-}
diff --git a/plugins/tangle/tangle.go b/plugins/tangle/tangle.go
new file mode 100644
index 00000000..6862e9aa
--- /dev/null
+++ b/plugins/tangle/tangle.go
@@ -0,0 +1,71 @@
+package tangle
+
+import (
+	"github.com/iotaledger/goshimmer/packages/binary/storageprefix"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transactionmetadata"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/tipselector"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/transactionparser"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/transactionrequester"
+	"github.com/iotaledger/goshimmer/packages/shutdown"
+	"github.com/iotaledger/hive.go/daemon"
+	"github.com/iotaledger/hive.go/events"
+
+	"github.com/iotaledger/goshimmer/packages/binary/tangle"
+
+	"github.com/iotaledger/hive.go/logger"
+	"github.com/iotaledger/hive.go/node"
+)
+
+var PLUGIN = node.NewPlugin("Tangle", node.Enabled, configure, run)
+
+var TransactionParser *transactionparser.TransactionParser
+
+var TransactionRequester *transactionrequester.TransactionRequester
+
+var TipSelector *tipselector.TipSelector
+
+var Instance *tangle.Tangle
+
+var log *logger.Logger
+
+func configure(*node.Plugin) {
+	log = logger.NewLogger("Tangle")
+
+	// create instances
+	TransactionParser = transactionparser.New()
+	TransactionRequester = transactionrequester.New()
+	TipSelector = tipselector.New()
+	Instance = tangle.New(storageprefix.Mainnet)
+
+	// setup TransactionParser
+	TransactionParser.Events.TransactionParsed.Attach(events.NewClosure(func(transaction *transaction.Transaction) {
+		Instance.AttachTransaction(transaction)
+	}))
+
+	// setup TransactionRequester
+	Instance.Events.TransactionMissing.Attach(events.NewClosure(TransactionRequester.ScheduleRequest))
+	Instance.Events.MissingTransactionReceived.Attach(events.NewClosure(func(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) {
+		cachedTransactionMetadata.Release()
+
+		cachedTransaction.Consume(func(transaction *transaction.Transaction) {
+			TransactionRequester.StopRequest(transaction.GetId())
+		})
+	}))
+
+	// setup TipSelector
+	Instance.Events.TransactionSolid.Attach(events.NewClosure(func(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) {
+		cachedTransactionMetadata.Release()
+
+		cachedTransaction.Consume(TipSelector.AddTip)
+	}))
+}
+
+func run(*node.Plugin) {
+	daemon.BackgroundWorker("Tangle", func(shutdownSignal <-chan struct{}) {
+		<-shutdownSignal
+
+		TransactionParser.Shutdown()
+		Instance.Shutdown()
+	}, shutdown.ShutdownPriorityTangle)
+}
diff --git a/plugins/tangle/transaction.go b/plugins/tangle/transaction.go
deleted file mode 100644
index bff7b6b7..00000000
--- a/plugins/tangle/transaction.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package tangle
-
-import (
-	"fmt"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/hive.go/lru_cache"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region public api ///////////////////////////////////////////////////////////////////////////////////////////////////
-
-func GetTransaction(transactionHash trinary.Trytes, computeIfAbsent ...func(trinary.Trytes) *value_transaction.ValueTransaction) (result *value_transaction.ValueTransaction, err error) {
-	if cacheResult := transactionCache.ComputeIfAbsent(transactionHash, func() interface{} {
-		if transaction, dbErr := getTransactionFromDatabase(transactionHash); dbErr != nil {
-			err = dbErr
-
-			return nil
-		} else if transaction != nil {
-			return transaction
-		} else {
-			if len(computeIfAbsent) >= 1 {
-				return computeIfAbsent[0](transactionHash)
-			}
-
-			return nil
-		}
-	}); !typeutils.IsInterfaceNil(cacheResult) {
-		result = cacheResult.(*value_transaction.ValueTransaction)
-	}
-
-	return
-}
-
-func ContainsTransaction(transactionHash trinary.Trytes) (result bool, err error) {
-	if transactionCache.Contains(transactionHash) {
-		result = true
-	} else {
-		result, err = databaseContainsTransaction(transactionHash)
-	}
-
-	return
-}
-
-func StoreTransaction(transaction *value_transaction.ValueTransaction) {
-	transactionCache.Set(transaction.GetHash(), transaction)
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region lru cache ////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var transactionCache = lru_cache.NewLRUCache(TRANSACTION_CACHE_SIZE, &lru_cache.LRUCacheOptions{
-	EvictionCallback:  onEvictTransactions,
-	EvictionBatchSize: 200,
-})
-
-func onEvictTransactions(_ interface{}, values interface{}) {
-	// TODO: replace with apply
-	for _, obj := range values.([]interface{}) {
-		if tx := obj.(*value_transaction.ValueTransaction); tx.GetModified() {
-			if err := storeTransactionInDatabase(tx); err != nil {
-				panic(err)
-			}
-		}
-	}
-}
-
-func FlushTransactionCache() {
-	transactionCache.DeleteAll()
-}
-
-const (
-	TRANSACTION_CACHE_SIZE = 500
-)
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region database /////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var transactionDatabase database.Database
-
-func configureTransactionDatabase() {
-	if db, err := database.Get(database.DBPrefixTransaction, database.GetBadgerInstance()); err != nil {
-		panic(err)
-	} else {
-		transactionDatabase = db
-	}
-}
-
-func storeTransactionInDatabase(transaction *value_transaction.ValueTransaction) error {
-	if transaction.GetModified() {
-		if err := transactionDatabase.Set(database.Entry{Key: typeutils.StringToBytes(transaction.GetHash()), Value: transaction.MetaTransaction.GetBytes()}); err != nil {
-			return fmt.Errorf("%w: failed to store transaction: %s", ErrDatabaseError, err.Error())
-		}
-		transaction.SetModified(false)
-	}
-
-	return nil
-}
-
-func getTransactionFromDatabase(transactionHash trinary.Trytes) (*value_transaction.ValueTransaction, error) {
-	txData, err := transactionDatabase.Get(typeutils.StringToBytes(transactionHash))
-	if err != nil {
-		if err == database.ErrKeyNotFound {
-			return nil, nil
-		}
-		return nil, fmt.Errorf("%w: failed to retrieve transaction: %s", ErrDatabaseError, err)
-	}
-
-	return value_transaction.FromBytes(txData.Value), nil
-}
-
-func databaseContainsTransaction(transactionHash trinary.Trytes) (bool, error) {
-	if contains, err := transactionDatabase.Contains(typeutils.StringToBytes(transactionHash)); err != nil {
-		return contains, fmt.Errorf("%w: failed to check if the transaction exists: %s", ErrDatabaseError, err)
-	} else {
-		return contains, nil
-	}
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/tangle/transaction_metadata.go b/plugins/tangle/transaction_metadata.go
deleted file mode 100644
index 152f0126..00000000
--- a/plugins/tangle/transaction_metadata.go
+++ /dev/null
@@ -1,134 +0,0 @@
-package tangle
-
-import (
-	"fmt"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/goshimmer/packages/model/transactionmetadata"
-	"github.com/iotaledger/hive.go/lru_cache"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-// region public api ///////////////////////////////////////////////////////////////////////////////////////////////////
-
-func GetTransactionMetadata(transactionHash trinary.Trytes, computeIfAbsent ...func(trinary.Trytes) *transactionmetadata.TransactionMetadata) (result *transactionmetadata.TransactionMetadata, err error) {
-	if cacheResult := transactionMetadataCache.ComputeIfAbsent(transactionHash, func() interface{} {
-		if transactionMetadata, dbErr := getTransactionMetadataFromDatabase(transactionHash); dbErr != nil {
-			err = dbErr
-
-			return nil
-		} else if transactionMetadata != nil {
-			return transactionMetadata
-		} else {
-			if len(computeIfAbsent) >= 1 {
-				return computeIfAbsent[0](transactionHash)
-			}
-
-			return nil
-		}
-	}); !typeutils.IsInterfaceNil(cacheResult) {
-		result = cacheResult.(*transactionmetadata.TransactionMetadata)
-	}
-
-	return
-}
-
-func ContainsTransactionMetadata(transactionHash trinary.Trytes) (result bool, err error) {
-	if transactionMetadataCache.Contains(transactionHash) {
-		result = true
-	} else {
-		result, err = databaseContainsTransactionMetadata(transactionHash)
-	}
-
-	return
-}
-
-func StoreTransactionMetadata(transactionMetadata *transactionmetadata.TransactionMetadata) {
-	transactionMetadataCache.Set(transactionMetadata.GetHash(), transactionMetadata)
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region lru cache ////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var transactionMetadataCache = lru_cache.NewLRUCache(TRANSACTION_METADATA_CACHE_SIZE, &lru_cache.LRUCacheOptions{
-	EvictionCallback:  onEvictTransactionMetadatas,
-	EvictionBatchSize: 200,
-})
-
-func onEvictTransactionMetadatas(_ interface{}, values interface{}) {
-	// TODO: replace with apply
-	for _, obj := range values.([]interface{}) {
-		if txMetadata := obj.(*transactionmetadata.TransactionMetadata); txMetadata.GetModified() {
-			if err := storeTransactionMetadataInDatabase(txMetadata); err != nil {
-				panic(err)
-			}
-		}
-	}
-}
-
-func FlushTransactionMetadata() {
-	transactionCache.DeleteAll()
-}
-
-const (
-	TRANSACTION_METADATA_CACHE_SIZE = 500
-)
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// region database /////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var transactionMetadataDatabase database.Database
-
-func configureTransactionMetaDataDatabase() {
-	if db, err := database.Get(database.DBPrefixTransactionMetadata, database.GetBadgerInstance()); err != nil {
-		panic(err)
-	} else {
-		transactionMetadataDatabase = db
-	}
-}
-
-func storeTransactionMetadataInDatabase(metadata *transactionmetadata.TransactionMetadata) error {
-	if metadata.GetModified() {
-		if marshaledMetadata, err := metadata.Marshal(); err != nil {
-			return err
-		} else {
-			if err := transactionMetadataDatabase.Set(database.Entry{Key: typeutils.StringToBytes(metadata.GetHash()), Value: marshaledMetadata}); err != nil {
-				return fmt.Errorf("%w: failed to store transaction metadata: %s", ErrDatabaseError, err)
-			}
-
-			metadata.SetModified(false)
-		}
-	}
-
-	return nil
-}
-
-func getTransactionMetadataFromDatabase(transactionHash trinary.Trytes) (*transactionmetadata.TransactionMetadata, error) {
-	txMetadata, err := transactionMetadataDatabase.Get(typeutils.StringToBytes(transactionHash))
-	if err != nil {
-		if err == database.ErrKeyNotFound {
-			return nil, nil
-		}
-		return nil, fmt.Errorf("%w: failed to retrieve transaction: %s", ErrDatabaseError, err)
-	}
-
-	var result transactionmetadata.TransactionMetadata
-	if err := result.Unmarshal(txMetadata.Value); err != nil {
-		panic(err)
-	}
-
-	return &result, nil
-}
-
-func databaseContainsTransactionMetadata(transactionHash trinary.Trytes) (bool, error) {
-	if contains, err := transactionMetadataDatabase.Contains(typeutils.StringToBytes(transactionHash)); err != nil {
-		return contains, fmt.Errorf("%w: failed to check if the transaction metadata exists: %s", ErrDatabaseError, err)
-	} else {
-		return contains, nil
-	}
-}
-
-// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/tangle/tx_per_address.go b/plugins/tangle/tx_per_address.go
deleted file mode 100644
index 092a7524..00000000
--- a/plugins/tangle/tx_per_address.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package tangle
-
-import (
-	"fmt"
-
-	"github.com/iotaledger/goshimmer/packages/database"
-	"github.com/iotaledger/hive.go/typeutils"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-var (
-	transactionsHashesForAddressDatabase database.Database
-)
-
-func configureTransactionHashesForAddressDatabase() {
-	if db, err := database.Get(database.DBPrefixAddressTransactions, database.GetBadgerInstance()); err != nil {
-		panic(err)
-	} else {
-		transactionsHashesForAddressDatabase = db
-	}
-}
-
-type TxHashForAddress struct {
-	Address trinary.Hash
-	TxHash  trinary.Hash
-}
-
-func StoreTransactionHashForAddressInDatabase(address *TxHashForAddress) error {
-	if err := transactionsHashesForAddressDatabase.Set(database.Entry{
-		Key:   databaseKeyForHashPrefixedHash(address.Address, address.TxHash),
-		Value: []byte{},
-	}); err != nil {
-		return fmt.Errorf("%w: failed to store tx for address in database: %s", ErrDatabaseError, err)
-	}
-	return nil
-}
-
-func DeleteTransactionHashForAddressInDatabase(address *TxHashForAddress) error {
-	if err := transactionsHashesForAddressDatabase.Delete(
-		databaseKeyForHashPrefixedHash(address.Address, address.TxHash),
-	); err != nil {
-		return fmt.Errorf("%w: failed to delete tx for address: %s", ErrDatabaseError, err)
-	}
-
-	return nil
-}
-
-func ReadTransactionHashesForAddressFromDatabase(address trinary.Hash) ([]trinary.Hash, error) {
-	var transactionHashes []trinary.Hash
-	err := transactionsHashesForAddressDatabase.StreamForEachPrefixKeyOnly(databaseKeyForHashPrefix(address), func(key database.KeyOnlyEntry) error {
-		transactionHashes = append(transactionHashes, typeutils.BytesToString(key.Key))
-		return nil
-	})
-
-	if err != nil {
-		return nil, fmt.Errorf("%w: failed to read tx per address from database: %s", ErrDatabaseError, err)
-	}
-	return transactionHashes, nil
-}
diff --git a/plugins/tangle/unsolidTxs.go b/plugins/tangle/unsolidTxs.go
deleted file mode 100644
index 36924fa7..00000000
--- a/plugins/tangle/unsolidTxs.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package tangle
-
-import (
-	"sync"
-	"time"
-)
-
-type UnsolidTxs struct {
-	internal map[string]Info
-	sync.RWMutex
-}
-
-type Info struct {
-	lastRequest time.Time
-	counter     int
-}
-
-func NewUnsolidTxs() *UnsolidTxs {
-	return &UnsolidTxs{
-		internal: make(map[string]Info),
-	}
-}
-
-func (u *UnsolidTxs) Add(hash string) bool {
-	u.Lock()
-	defer u.Unlock()
-	_, contains := u.internal[hash]
-	if contains {
-		return false
-	}
-	info := Info{
-		lastRequest: time.Now(),
-		counter:     1,
-	}
-	u.internal[hash] = info
-	return true
-}
-
-func (u *UnsolidTxs) Remove(hash string) {
-	u.Lock()
-	delete(u.internal, hash)
-	u.Unlock()
-}
-
-func (u *UnsolidTxs) Update(targetTime time.Time) (result []string) {
-	u.Lock()
-	for k, v := range u.internal {
-		if v.lastRequest.Before(targetTime) {
-			result = append(result, k)
-
-			v.lastRequest = time.Now()
-			v.counter++
-
-			u.internal[k] = v
-		}
-	}
-	u.Unlock()
-	return result
-}
diff --git a/plugins/tipselection/plugin.go b/plugins/tipselection/plugin.go
deleted file mode 100644
index 7587075e..00000000
--- a/plugins/tipselection/plugin.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package tipselection
-
-import (
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/hive.go/events"
-	"github.com/iotaledger/hive.go/node"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-var PLUGIN = node.NewPlugin("Tipselection", node.Enabled, configure, run)
-
-func configure(*node.Plugin) {
-	tipSet = make(map[trinary.Hash]struct{})
-
-	tangle.Events.TransactionSolid.Attach(events.NewClosure(func(transaction *value_transaction.ValueTransaction) {
-		mutex.Lock()
-		defer mutex.Unlock()
-
-		delete(tipSet, transaction.GetBranchTransactionHash())
-		delete(tipSet, transaction.GetTrunkTransactionHash())
-		tipSet[transaction.GetHash()] = struct{}{}
-	}))
-}
-
-func run(*node.Plugin) {
-}
diff --git a/plugins/tipselection/tipselection.go b/plugins/tipselection/tipselection.go
deleted file mode 100644
index 95cb4bc1..00000000
--- a/plugins/tipselection/tipselection.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package tipselection
-
-import (
-	"math/rand"
-	"sync"
-
-	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
-	"github.com/iotaledger/iota.go/trinary"
-)
-
-var (
-	tipSet map[trinary.Hash]struct{}
-	mutex  sync.RWMutex
-)
-
-func GetRandomTip(excluding ...trinary.Hash) trinary.Trytes {
-	mutex.RLock()
-	defer mutex.RUnlock()
-
-	numTips := len(tipSet)
-	if numTips == 0 {
-		return meta_transaction.BRANCH_NULL_HASH
-	}
-
-	var ignore trinary.Hash
-	if len(excluding) > 0 {
-		ignore = excluding[0]
-	}
-	if _, contains := tipSet[ignore]; contains {
-		if numTips == 1 {
-			return ignore
-		}
-		numTips -= 1
-	}
-
-	i := rand.Intn(numTips)
-	for k := range tipSet {
-		if k == ignore {
-			continue
-		}
-		if i == 0 {
-			return k
-		}
-		i--
-	}
-	panic("unreachable")
-}
-
-func GetTipsCount() int {
-	mutex.RLock()
-	defer mutex.RUnlock()
-
-	return len(tipSet)
-}
diff --git a/plugins/tipselection/tipselection_test.go b/plugins/tipselection/tipselection_test.go
deleted file mode 100644
index cb18e478..00000000
--- a/plugins/tipselection/tipselection_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package tipselection
-
-import (
-	"log"
-	"testing"
-
-	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/plugins/tangle"
-	"github.com/iotaledger/hive.go/logger"
-	"github.com/spf13/viper"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func init() {
-	if err := logger.InitGlobalLogger(viper.New()); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func TestEmptyTipSet(t *testing.T) {
-	configure(nil)
-	assert.Equal(t, 0, GetTipsCount())
-	assert.Equal(t, meta_transaction.BRANCH_NULL_HASH, GetRandomTip())
-}
-
-func TestSingleTip(t *testing.T) {
-	configure(nil)
-
-	tx := value_transaction.New()
-	tx.SetValue(int64(1))
-	tx.SetBranchTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-	tx.SetTrunkTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-
-	tangle.Events.TransactionSolid.Trigger(tx)
-
-	assert.Equal(t, 1, GetTipsCount())
-
-	tip1 := GetRandomTip()
-	assert.NotNil(t, tip1)
-	tip2 := GetRandomTip(tip1)
-	assert.NotNil(t, tip2)
-	assert.Equal(t, tip1, tip2)
-}
-
-func TestGetRandomTip(t *testing.T) {
-	configure(nil)
-
-	tx := value_transaction.New()
-	tx.SetValue(int64(1))
-	tx.SetBranchTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-	tx.SetTrunkTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-
-	tangle.Events.TransactionSolid.Trigger(tx)
-
-	tx = value_transaction.New()
-	tx.SetValue(int64(2))
-	tx.SetBranchTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-	tx.SetTrunkTransactionHash(meta_transaction.BRANCH_NULL_HASH)
-
-	tangle.Events.TransactionSolid.Trigger(tx)
-
-	assert.Equal(t, 2, GetTipsCount())
-
-	tip1 := GetRandomTip()
-	require.NotNil(t, tip1)
-	tip2 := GetRandomTip(tip1)
-	require.NotNil(t, tip2)
-	require.NotEqual(t, tip1, tip2)
-
-	tx = value_transaction.New()
-	tx.SetValue(int64(3))
-	tx.SetBranchTransactionHash(tip1)
-	tx.SetTrunkTransactionHash(tip2)
-
-	tangle.Events.TransactionSolid.Trigger(tx)
-
-	assert.Equal(t, 1, GetTipsCount())
-	assert.Equal(t, tx.GetHash(), GetRandomTip())
-}
diff --git a/plugins/webapi/findTransactionHashes/plugin.go b/plugins/webapi/findTransactionHashes/plugin.go
index 7ae655f8..29d573f1 100644
--- a/plugins/webapi/findTransactionHashes/plugin.go
+++ b/plugins/webapi/findTransactionHashes/plugin.go
@@ -3,7 +3,6 @@ package findTransactionHashes
 import (
 	"net/http"
 
-	"github.com/iotaledger/goshimmer/plugins/tangle"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
@@ -24,24 +23,29 @@ func configure(plugin *node.Plugin) {
 // If a node doesn't have any transaction hash for a given address in its ledger,
 // the value at the index of that address is empty.
 func findTransactionHashes(c echo.Context) error {
-	var request Request
-
-	if err := c.Bind(&request); err != nil {
-		log.Info(err.Error())
-		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
-	}
-	log.Debug("Received:", request.Addresses)
-	result := make([][]trinary.Trytes, len(request.Addresses))
-
-	for i, address := range request.Addresses {
-		txs, err := tangle.ReadTransactionHashesForAddressFromDatabase(address)
-		if err != nil {
-			return c.JSON(http.StatusInternalServerError, Response{Error: err.Error()})
+	return c.JSON(http.StatusInternalServerError, Response{Error: "TODO: ADD LOGIC ACCORDING TO VALUE TANGLE"})
+
+	// TODO: ADD LOGIC ACCORDING TO VALUE TANGLE
+	/*
+		var request Request
+
+		if err := c.Bind(&request); err != nil {
+			log.Info(err.Error())
+			return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
+		}
+		log.Debug("Received:", request.Addresses)
+		result := make([][]trinary.Trytes, len(request.Addresses))
+
+		for i, address := range request.Addresses {
+			txs, err := tangle_old.ReadTransactionHashesForAddressFromDatabase(address)
+			if err != nil {
+				return c.JSON(http.StatusInternalServerError, Response{Error: err.Error()})
+			}
+			result[i] = append(result[i], txs...)
 		}
-		result[i] = append(result[i], txs...)
-	}
 
-	return c.JSON(http.StatusOK, Response{Transactions: result})
+		return c.JSON(http.StatusOK, Response{Transactions: result})
+	*/
 }
 
 type Response struct {
diff --git a/plugins/webapi/getTransactionObjectsByHash/plugin.go b/plugins/webapi/getTransactionObjectsByHash/plugin.go
index e2b0e766..3432944c 100644
--- a/plugins/webapi/getTransactionObjectsByHash/plugin.go
+++ b/plugins/webapi/getTransactionObjectsByHash/plugin.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"net/http"
 
-	"github.com/iotaledger/goshimmer/plugins/tangle"
+	"github.com/iotaledger/goshimmer/plugins/tangle_old"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
@@ -37,7 +37,7 @@ func getTransactionObjectsByHash(c echo.Context) error {
 	log.Debug("Received:", request.Hashes)
 
 	for _, hash := range request.Hashes {
-		tx, err := tangle.GetTransaction(hash)
+		tx, err := tangle_old.GetTransaction(hash)
 		if err != nil {
 			return c.JSON(http.StatusInternalServerError, Response{Error: err.Error()})
 		}
diff --git a/plugins/webapi/getTransactionTrytesByHash/plugin.go b/plugins/webapi/getTransactionTrytesByHash/plugin.go
index 8cb79778..e13c39c0 100644
--- a/plugins/webapi/getTransactionTrytesByHash/plugin.go
+++ b/plugins/webapi/getTransactionTrytesByHash/plugin.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"net/http"
 
-	"github.com/iotaledger/goshimmer/plugins/tangle"
+	"github.com/iotaledger/goshimmer/plugins/tangle_old"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
@@ -35,7 +35,7 @@ func getTransactionTrytesByHash(c echo.Context) error {
 	log.Debug("Received:", request.Hashes)
 
 	for _, hash := range request.Hashes {
-		tx, err := tangle.GetTransaction(hash)
+		tx, err := tangle_old.GetTransaction(hash)
 		if err != nil {
 			return c.JSON(http.StatusInternalServerError, Response{Error: err.Error()})
 		}
-- 
GitLab