Repository: NethermindEth/juno
Pull request #158 (2022-05-18 15:09:53)

Update Database on project
- Add transaction database (oriented to transactions)
- Minor changes on names and comments

codecov[bot]: # [Codecov](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) Report
> Merging [#158](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) (44229d0) into [main](https://codecov.io/gh/NethermindEth/juno/commit/ca6026aaf3b2986b94dac90c92d159ee6f93079b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) (ca6026a) will **decrease** coverage by `1.01%`.
> The diff coverage is `61.85%`.

```diff
@@             Coverage Diff             @@
##              main     #158      +/-   ##
===========================================
- Coverage   100.00%   98.98%   -1.02%     
===========================================
  Files           31       33       +2     
  Lines         3577     3659      +82     
===========================================
+ Hits          3577     3622      +45     
- Misses           0       36      +36     
- Partials         0        1       +1     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `98.98% <61.85%> (-1.02%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) | Coverage Δ | |
|---|---|---|
| [pkg/db/kvStorer.go](https://codecov.io/gh/NethermindEth/juno/pull/158/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-cGtnL2RiL2t2U3RvcmVyLmdv) | `0.00% <0.00%> (ø)` | |
| [pkg/db/db.go](https://codecov.io/gh/NethermindEth/juno/pull/158/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-cGtnL2RiL2RiLmdv) | `91.66% <58.33%> (-8.34%)` | :arrow_down: |
| [pkg/db/transactionDb.go](https://codecov.io/gh/NethermindEth/juno/pull/158/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-cGtnL2RiL3RyYW5zYWN0aW9uRGIuZ28=) | `91.37% <91.37%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth). Last update [ca6026a...44229d0](https://codecov.io/gh/NethermindEth/juno/pull/158?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth).

stdevAdrianPaez: > Looks good but just a couple of issues:
> 
> 1. The `db` package is becoming increasingly specialised to Juno's requirements so I think we should have this moved to the `internal` in the root directory of the repository.
> 2. Although not documented, the file name convention is all lowercase or lowercase with underscores. I have a preference for the former as `_xxx.go` prefixes tend to be used as directives on how the toolchain interacts with these files i.e. `_test.go`, `_linux.go`, `_arm.go`, and so on. ([See issue](https://github.com/golang/go/issues/36060)).
> 3. It is not clear to me why is the `abi`, `state`, and `transaction` packages coupled with the database. If they are related to how such objects are handled by the database then they should be under an `internal` directory under `db` which is also makes point 1. more pertinent. Shouldn't we also apply similar treatment to blocks as well? So instead of `blockSpecific` we could have `block` and treat that similarly to `state` and `transaction`?
> 4. Using separators i.e. `268_435_456` and providing more context on the values that set the geometry might improve readability.
> 5. Do we need a separate `db_test` package?

**About 3.** :`db` package has a simple database implementation without any data type associated, and `abi`, `state` and `transactions` are databases for each of that types
stdevAdrianPaez: > Looks good but just a couple of issues:
> 
> 1. The `db` package is becoming increasingly specialised to Juno's requirements so I think we should have this moved to the `internal` in the root directory of the repository.
> 2. Although not documented, the file name convention is all lowercase or lowercase with underscores. I have a preference for the former as `_xxx.go` prefixes tend to be used as directives on how the toolchain interacts with these files i.e. `_test.go`, `_linux.go`, `_arm.go`, and so on. ([See issue](https://github.com/golang/go/issues/36060)).
> 3. It is not clear to me why is the `abi`, `state`, and `transaction` packages coupled with the database. If they are related to how such objects are handled by the database then they should be under an `internal` directory under `db` which is also makes point 1. more pertinent. Shouldn't we also apply similar treatment to blocks as well? So instead of `blockSpecific` we could have `block` and treat that similarly to `state` and `transaction`?
> 4. Using separators i.e. `268_435_456` and providing more context on the values that set the geometry might improve readability.
> 5. Do we need a separate `db_test` package?

**Abou 3.:** `blockSpecific` is a kind of database used to store values that can change in a block and we need to get the correct value in a specific block too. An example of that is contract storage, because the storage may change in a transaction. Not confuse it with storing the blocks. To store the blocks we use a simple key-value database without any version control.

Patch:
diff --git a/pkg/db/abi/abi.go b/internal/db/abi/abi.go
similarity index 100%
rename from pkg/db/abi/abi.go
rename to internal/db/abi/abi.go
diff --git a/pkg/db/abi/abi_test.go b/internal/db/abi/abi_test.go
similarity index 100%
rename from pkg/db/abi/abi_test.go
rename to internal/db/abi/abi_test.go
diff --git a/pkg/db/abi/manager.go b/internal/db/abi/manager.go
similarity index 97%
rename from pkg/db/abi/manager.go
rename to internal/db/abi/manager.go
index 0426c4e7..4ea217a0 100644
--- a/pkg/db/abi/manager.go
+++ b/internal/db/abi/manager.go
@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/NethermindEth/juno/pkg/db"
+	"github.com/NethermindEth/juno/internal/db"
 	"math/big"
 )
 
diff --git a/pkg/db/db.go b/internal/db/db.go
similarity index 65%
rename from pkg/db/db.go
rename to internal/db/db.go
index 5b12f635..6f591083 100644
--- a/pkg/db/db.go
+++ b/internal/db/db.go
@@ -23,12 +23,10 @@ type Databaser interface {
 	Delete(key []byte) error
 	// NumberOfItems returns the number of items in the database.
 	NumberOfItems() (uint64, error)
-	// Begin starts a new transaction.
-	Begin()
-	// Rollback rollsback the database to a previous state.
-	Rollback()
 	// Close closes the environment.
 	Close()
+	// GetEnv returns the environment of the database
+	GetEnv() *mdbx.Env
 }
 
 // KeyValueDb represents the middleware for an MDBX key-value store.
@@ -37,35 +35,42 @@ type KeyValueDb struct {
 	path string
 }
 
-// New creates a new key-value database.
-func New(path string, flags uint) *KeyValueDb {
-	log.Default.With("Path", path, "Flags", flags).Info("Creating new database.")
+// GetEnv returns the environment of the database
+func (d *KeyValueDb) GetEnv() *mdbx.Env {
+	return d.env
+}
+
+// NewKeyValueDbWithEnv creates a new key-value database based on an already created env.
+func NewKeyValueDbWithEnv(env *mdbx.Env, path string) *KeyValueDb {
+	return &KeyValueDb{
+		env:  env,
+		path: path,
+	}
+}
+
+func NewKeyValueDb(path string, flags uint) *KeyValueDb {
 	env, err := mdbx.NewEnv()
 	if err != nil {
 		// notest
-		log.Default.With("Error", err).Info("Failed to initialise and allocate new mdbx.Env.")
 		return nil
 	}
 
 	// Set flags.
 	// Based on https://github.com/torquem-ch/mdbx-go/blob/96f31f483af593377e52358a079e834256d5af55/mdbx/env_test.go#L495
-	err = env.SetOption(mdbx.OptMaxDB, 1024)
+	err = env.SetOption(mdbx.OptMaxDB, 1)
 	if err != nil {
 		// notest
-		log.Default.With("Error", err).Info("Failed to set mdbx.Env options.")
 		return nil
 	}
 	const pageSize = 4096
-	err = env.SetGeometry(-1, -1, 64*1024*pageSize, -1, -1, pageSize)
+	err = env.SetGeometry(268435456, 268435456, 25769803776, 268435456, 268435456, pageSize)
 	if err != nil {
 		// notest
-		log.Default.With("Error", err).Info("Failed to set geometry.")
 		return nil
 	}
-	err = env.Open(path, flags, 0664)
+	err = env.Open(path, flags|mdbx.Exclusive, 0664)
 	if err != nil {
 		// notest
-		log.Default.With("Error", err).Info("Failed to open mdbx.Env.")
 		return nil
 	}
 	return &KeyValueDb{env: env, path: path}
@@ -76,7 +81,6 @@ func New(path string, flags uint) *KeyValueDb {
 func (d *KeyValueDb) Has(key []byte) (has bool, err error) {
 	val, err := d.getOne(key)
 	if err != nil {
-		log.Default.With("Error", err, "Key", string(key)).Info("Key provided does not exist.")
 		return false, err
 	}
 	return val != nil, nil
@@ -89,17 +93,14 @@ func (d *KeyValueDb) getOne(key []byte) (val []byte, err error) {
 	if err := d.env.View(func(txn *mdbx.Txn) error {
 		dbi, err = txn.OpenRoot(mdbx.Create)
 		if err != nil {
-			log.Default.With("Error", err).Info("Failed to open database.")
 			return err
 		}
 		val, err = txn.Get(dbi, key)
 		if err != nil {
 			if mdbx.IsNotFound(err) {
-				log.Default.With("Error", err, "Key", string(key)).Info("Failed to get value.")
 				err = nil
 				return nil
 			}
-			log.Default.With("Error", err, "Key", string(key)).Info("Failed to get value.")
 			return err
 		}
 		return nil
@@ -113,21 +114,16 @@ func (d *KeyValueDb) getOne(key []byte) (val []byte, err error) {
 // Get returns the value associated with the provided key in the
 // database or returns an error otherwise.
 func (d *KeyValueDb) Get(key []byte) ([]byte, error) {
-	log.Default.With("Key", key).Info("Getting value using key.")
 	return d.getOne(key)
 }
 
 // Put inserts a key-value pair into the database.
 func (d *KeyValueDb) Put(key, value []byte) error {
-	log.Default.With("Key", string(key)).Info("Putting value at key.")
 	err := d.env.Update(func(txn *mdbx.Txn) error {
-		log.Default.Info("Opening the root database.")
 		dbi, err := txn.OpenRoot(mdbx.Create)
 		if err != nil {
-			log.Default.With("Error", err, "Key", string(key)).Info("Unable to open root database.")
 			return err
 		}
-		log.Default.Info("Storing item in database.")
 		return txn.Put(dbi, key, value, 0)
 	})
 	return err
@@ -135,16 +131,13 @@ func (d *KeyValueDb) Put(key, value []byte) error {
 
 // Delete removes a previous inserted key or returns an error otherwise.
 func (d *KeyValueDb) Delete(key []byte) error {
-	log.Default.With("Key", key).Info("Deleting value associated with key.")
 	err := d.env.Update(func(txn *mdbx.Txn) error {
 		db, err := txn.OpenRoot(mdbx.Create)
 		if err != nil {
-			log.Default.With("Error", err, "Key", string(key)).Info("Unable to open database.")
 			return err
 		}
 		err = txn.Del(db, key, nil)
 		if mdbx.IsNotFound(err) {
-			log.Default.With("Error", err, "Key", string(key)).Info("Unable to get value.")
 			return nil
 		}
 		return err
@@ -154,21 +147,15 @@ func (d *KeyValueDb) Delete(key []byte) error {
 
 // NumberOfItems returns the number of items in the database.
 func (d *KeyValueDb) NumberOfItems() (uint64, error) {
-	log.Default.Info("Getting the number of items in the database.")
 	stats, err := d.env.Stat()
 	if err != nil {
+		// notest
 		log.Default.With("Error", err).Info("Unable to get stats from env.")
 		return 0, err
 	}
 	return stats.Entries, err
 }
 
-// Begin starts a new transaction.
-func (d KeyValueDb) Begin() {}
-
-// Rollback rolls back the database to a previous state.
-func (d KeyValueDb) Rollback() {}
-
 // Close closes the environment.
 func (d *KeyValueDb) Close() {
 	d.env.Close()
diff --git a/internal/db/kv_storer.go b/internal/db/kv_storer.go
new file mode 100644
index 00000000..8bade020
--- /dev/null
+++ b/internal/db/kv_storer.go
@@ -0,0 +1,51 @@
+package db
+
+// KeyValueStore implement the Storer interface that use a Databaser
+type KeyValueStore struct {
+	db     Databaser
+	prefix []byte
+}
+
+func NewKeyValueStore(db Databaser, prefix string) KeyValueStore {
+	return KeyValueStore{
+		db:     db,
+		prefix: []byte(prefix),
+	}
+}
+
+func (k KeyValueStore) Delete(key []byte) {
+	err := k.db.Delete(append(k.prefix, key...))
+	if err != nil {
+		// notest
+		return
+	}
+}
+
+func (k KeyValueStore) Get(key []byte) ([]byte, bool) {
+	get, err := k.db.Get(append(k.prefix, key...))
+	if err != nil {
+		// notest
+		return nil, false
+	}
+	return get, get != nil
+}
+
+func (k KeyValueStore) Put(key, val []byte) {
+	err := k.db.Put(append(k.prefix, key...), val)
+	if err != nil {
+		// notest
+		return
+	}
+}
+
+func (k KeyValueStore) Begin() {
+
+}
+
+func (k KeyValueStore) Rollback() {
+
+}
+
+func (k KeyValueStore) Close() {
+	k.db.Close()
+}
diff --git a/pkg/db/state/state.go b/internal/db/state/state.go
similarity index 71%
rename from pkg/db/state/state.go
rename to internal/db/state/state.go
index 492e0987..4943d046 100644
--- a/pkg/db/state/state.go
+++ b/internal/db/state/state.go
@@ -2,7 +2,7 @@ package state
 
 import (
 	"errors"
-	"github.com/NethermindEth/juno/pkg/db"
+	db2 "github.com/NethermindEth/juno/internal/db"
 )
 
 var (
@@ -15,11 +15,11 @@ var (
 // Manager is a database manager, with the objective of managing
 // the contract codes and contract storages databases.
 type Manager struct {
-	codeDatabase    db.Databaser
-	storageDatabase db.BlockSpecificDatabase
+	codeDatabase    db2.Databaser
+	storageDatabase db2.BlockSpecificDatabase
 }
 
 // NewStateManager returns a new instance of Manager with the given database sources.
-func NewStateManager(codeDatabase db.Databaser, storageDatabase db.BlockSpecificDatabase) *Manager {
+func NewStateManager(codeDatabase db2.Databaser, storageDatabase db2.BlockSpecificDatabase) *Manager {
 	return &Manager{codeDatabase, storageDatabase}
 }
diff --git a/pkg/db/state/test_assets/contract-codes/Code-1.json b/internal/db/state/test_assets/contract-codes/Code-1.json
similarity index 100%
rename from pkg/db/state/test_assets/contract-codes/Code-1.json
rename to internal/db/state/test_assets/contract-codes/Code-1.json
diff --git a/pkg/db/state/test_assets/contract-codes/Code-2.json b/internal/db/state/test_assets/contract-codes/Code-2.json
similarity index 100%
rename from pkg/db/state/test_assets/contract-codes/Code-2.json
rename to internal/db/state/test_assets/contract-codes/Code-2.json
diff --git a/pkg/db/state/test_assets/contract-codes/Code-3.json b/internal/db/state/test_assets/contract-codes/Code-3.json
similarity index 100%
rename from pkg/db/state/test_assets/contract-codes/Code-3.json
rename to internal/db/state/test_assets/contract-codes/Code-3.json
diff --git a/pkg/db/state/test_assets/contract-codes/Code-4.json b/internal/db/state/test_assets/contract-codes/Code-4.json
similarity index 100%
rename from pkg/db/state/test_assets/contract-codes/Code-4.json
rename to internal/db/state/test_assets/contract-codes/Code-4.json
diff --git a/pkg/db/transaction/manager.go b/internal/db/transaction/manager.go
similarity index 98%
rename from pkg/db/transaction/manager.go
rename to internal/db/transaction/manager.go
index 7d6362a5..2cff950c 100644
--- a/pkg/db/transaction/manager.go
+++ b/internal/db/transaction/manager.go
@@ -1,8 +1,8 @@
 package transaction
 
 import (
+	"github.com/NethermindEth/juno/internal/db"
 	"github.com/NethermindEth/juno/internal/log"
-	"github.com/NethermindEth/juno/pkg/db"
 	"math/big"
 )
 
diff --git a/pkg/db/transaction/transaction.go b/internal/db/transaction/transaction.go
similarity index 100%
rename from pkg/db/transaction/transaction.go
rename to internal/db/transaction/transaction.go
diff --git a/internal/db/transaction_db.go b/internal/db/transaction_db.go
new file mode 100644
index 00000000..efb2ed2c
--- /dev/null
+++ b/internal/db/transaction_db.go
@@ -0,0 +1,144 @@
+package db
+
+import (
+	"github.com/NethermindEth/juno/internal/log"
+	"github.com/torquem-ch/mdbx-go/mdbx"
+	"runtime"
+)
+
+// Transactioner describes methods relating to an abstract key-value
+// database oriented to transactions.
+type Transactioner interface {
+	// Begin starts a new transaction.
+	Begin() Transaction
+}
+
+type Transaction interface {
+	Databaser
+	Commit() error
+	Rollback()
+}
+
+type TransactionDb struct {
+	env *mdbx.Env
+}
+
+type transaction struct {
+	txn *mdbx.Txn
+	env *mdbx.Env
+}
+
+// NewTransactionDb creates a new key-value database based on transactions.
+func NewTransactionDb(env *mdbx.Env) *TransactionDb {
+	return &TransactionDb{env: env}
+}
+
+func (d *TransactionDb) Begin() Transaction {
+	txn, err := d.env.BeginTxn(nil, 0)
+	if err != nil {
+		panic(any(err))
+	}
+	return &transaction{txn: txn, env: d.env}
+}
+
+// GetEnv returns the environment of the database
+func (d *transaction) GetEnv() *mdbx.Env {
+	return d.env
+}
+
+// Has returns true if the value at the provided key is in the
+// database.
+func (d *transaction) Has(key []byte) (has bool, err error) {
+	val, err := d.getOne(key)
+	if err != nil {
+		return false, err
+	}
+	return val != nil, nil
+}
+
+// getOne returns the value associated with the provided key in the
+// database or returns an error otherwise.
+func (d *transaction) getOne(key []byte) (val []byte, err error) {
+	var dbi mdbx.DBI
+	dbi, err = d.txn.OpenRoot(mdbx.Create)
+	if err != nil {
+		return nil, err
+	}
+	runtime.LockOSThread()
+	val, err = d.txn.Get(dbi, key)
+	if err != nil {
+		if mdbx.IsNotFound(err) {
+			err = nil
+			return nil, nil
+		}
+		return nil, err
+	}
+	runtime.UnlockOSThread()
+	return val, nil
+}
+
+// Get returns the value associated with the provided key in the
+// database or returns an error otherwise.
+func (d *transaction) Get(key []byte) ([]byte, error) {
+	return d.getOne(key)
+}
+
+// Put inserts a key-value pair into the database.
+func (d *transaction) Put(key, value []byte) error {
+	dbi, err := d.txn.OpenRoot(mdbx.Create)
+	if err != nil {
+		return err
+	}
+	runtime.LockOSThread()
+	err = d.txn.Put(dbi, key, value, 0)
+	runtime.UnlockOSThread()
+
+	return err
+}
+
+// Delete removes a previous inserted key or returns an error otherwise.
+func (d *transaction) Delete(key []byte) error {
+	db, err := d.txn.OpenRoot(mdbx.Create)
+	if err != nil {
+		return err
+	}
+	err = d.txn.Del(db, key, nil)
+	if mdbx.IsNotFound(err) {
+		return nil
+	}
+	return err
+}
+
+// NumberOfItems returns the number of items in the database.
+func (d *transaction) NumberOfItems() (uint64, error) {
+	stats, err := d.env.Stat()
+	if err != nil {
+		log.Default.With("Error", err).Info("Unable to get stats from env.")
+		return 0, err
+	}
+	return stats.Entries, err
+}
+
+// Close closes the environment.
+func (d *transaction) Close() {
+	d.env.Close()
+}
+
+// Commit saves all the information included in the current transaction
+func (d *transaction) Commit() error {
+	if d.txn != nil {
+		_, err := d.txn.Commit()
+		if err != nil {
+			d.txn = nil
+			return err
+		}
+	}
+	return nil
+}
+
+// Rollback rolls back the database to a previous state.
+func (d *transaction) Rollback() {
+	if d.txn != nil {
+		d.txn.Abort()
+	}
+}
diff --git a/internal/services/transactions.go b/internal/services/transactions.go
index f922113c..64ac4f3d 100644
--- a/internal/services/transactions.go
+++ b/internal/services/transactions.go
@@ -3,9 +3,9 @@ package services
 import (
 	"context"
 	"github.com/NethermindEth/juno/internal/config"
+	"github.com/NethermindEth/juno/internal/db"
+	"github.com/NethermindEth/juno/internal/db/transaction"
 	"github.com/NethermindEth/juno/internal/log"
-	"github.com/NethermindEth/juno/pkg/db"
-	"github.com/NethermindEth/juno/pkg/db/transaction"
 	"go.uber.org/zap"
 	"math/big"
 	"sync"
@@ -42,7 +42,7 @@ func (s *transactionService) Run() error {
 
 	if s.manager == nil {
 		// notest
-		database := db.New(config.DataDir+"/transaction", 0)
+		database := db.NewKeyValueDb(config.DataDir+"/transaction", 0)
 		s.manager = transaction.NewManager(database)
 	}
 


Test patch:
diff --git a/pkg/db/abi/manager_test.go b/internal/db/abi/manager_test.go
similarity index 92%
rename from pkg/db/abi/manager_test.go
rename to internal/db/abi/manager_test.go
index 7a8f8e51..6a90aa18 100644
--- a/pkg/db/abi/manager_test.go
+++ b/internal/db/abi/manager_test.go
@@ -3,7 +3,7 @@ package abi
 import (
 	"bytes"
 	"encoding/json"
-	"github.com/NethermindEth/juno/pkg/db"
+	"github.com/NethermindEth/juno/internal/db"
 	"testing"
 )
 
@@ -41,7 +41,7 @@ type testManagerPutABI struct {
 
 func TestManager(t *testing.T) {
 	// Init the ABI manager
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	manager := NewABIManager(database)
 	// Load ABI test files
 	abis, err := loadABIsFromFiles()
@@ -76,7 +76,7 @@ func TestManager(t *testing.T) {
 
 func TestManager_GetABI_NotFound(t *testing.T) {
 	// Init the ABI manager
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	manager := NewABIManager(database)
 	abi := manager.GetABI("1bd7ca87f139693e6681be2042194cf631c4e8d77027bf0ea9e6d55fc6018ac")
 	if abi != nil {
diff --git a/pkg/db/abi/test_assets/ABI-1.json b/internal/db/abi/test_assets/ABI-1.json
similarity index 100%
rename from pkg/db/abi/test_assets/ABI-1.json
rename to internal/db/abi/test_assets/ABI-1.json
diff --git a/pkg/db/abi/test_assets/ABI-2.json b/internal/db/abi/test_assets/ABI-2.json
similarity index 100%
rename from pkg/db/abi/test_assets/ABI-2.json
rename to internal/db/abi/test_assets/ABI-2.json
diff --git a/pkg/db/abi/test_assets/ABI-3.json b/internal/db/abi/test_assets/ABI-3.json
similarity index 100%
rename from pkg/db/abi/test_assets/ABI-3.json
rename to internal/db/abi/test_assets/ABI-3.json
diff --git a/pkg/db/abi/test_assets/ABI-4.json b/internal/db/abi/test_assets/ABI-4.json
similarity index 100%
rename from pkg/db/abi/test_assets/ABI-4.json
rename to internal/db/abi/test_assets/ABI-4.json
diff --git a/pkg/db/blockSpecific.go b/internal/db/block_specific.go
similarity index 100%
rename from pkg/db/blockSpecific.go
rename to internal/db/block_specific.go
diff --git a/pkg/db/blockSpecific_test.go b/internal/db/block_specific_test.go
similarity index 97%
rename from pkg/db/blockSpecific_test.go
rename to internal/db/block_specific_test.go
index 3bdc22f2..e9cbc977 100644
--- a/pkg/db/blockSpecific_test.go
+++ b/internal/db/block_specific_test.go
@@ -60,7 +60,7 @@ func TestBlockSpecificDatabase_Put(t *testing.T) {
 		},
 	}
 
-	database := New(t.TempDir(), 0)
+	database := NewKeyValueDb(t.TempDir(), 0)
 	db := NewBlockSpecificDatabase(database)
 
 	for _, test := range tests {
@@ -97,7 +97,7 @@ func TestBlockSpecificDatabase_Get(t *testing.T) {
 		},
 	}
 
-	database := New(t.TempDir(), 0)
+	database := NewKeyValueDb(t.TempDir(), 0)
 	db := NewBlockSpecificDatabase(database)
 
 	for _, d := range data {
diff --git a/pkg/db/db_test.go b/internal/db/db_test.go
similarity index 96%
rename from pkg/db/db_test.go
rename to internal/db/db_test.go
index 1dd2d916..3e6e7bd8 100644
--- a/pkg/db/db_test.go
+++ b/internal/db/db_test.go
@@ -16,7 +16,7 @@ func init() {
 
 // setupDatabaseForTest creates a new KVDatabase for Tests
 func setupDatabaseForTest(path string) *KeyValueDb {
-	return New(path, 0)
+	return NewKeyValueDb(path, 0)
 }
 
 // TestAddKey Check that a single value is inserted without error
@@ -207,14 +207,6 @@ func TestDelete(t *testing.T) {
 	}
 }
 
-func TestBegin(t *testing.T) {
-	database := setupDatabaseForTest(t.TempDir())
-	database.Begin()
-}
-func TestRollBack(t *testing.T) {
-	database := setupDatabaseForTest(t.TempDir())
-	database.Rollback()
-}
 func TestClose(t *testing.T) {
 	database := setupDatabaseForTest(t.TempDir())
 	database.Close()
@@ -225,6 +217,15 @@ func TestKeyValueDbIsDatabaser(t *testing.T) {
 	_ = Databaser(a)
 }
 
+func TestKeyValueDb_GetEnv(t *testing.T) {
+	database := setupDatabaseForTest(t.TempDir())
+	p := NewKeyValueDbWithEnv(database.GetEnv(), t.TempDir())
+	items, err := p.NumberOfItems()
+	if err != nil || items != 0 {
+		return
+	}
+}
+
 // BenchmarkEntriesInDatabase Benchmark the entry of key-value pairs to the db
 func BenchmarkEntriesInDatabase(b *testing.B) {
 	database := setupDatabaseForTest(b.TempDir())
diff --git a/internal/db/kv_storer_test.go b/internal/db/kv_storer_test.go
new file mode 100644
index 00000000..c00bf43e
--- /dev/null
+++ b/internal/db/kv_storer_test.go
@@ -0,0 +1,38 @@
+package db
+
+import (
+	"testing"
+)
+
+// setupTransactionDbTest creates a new TransactionDb for Tests
+func setupKvStoreTest(database Databaser) KeyValueStore {
+	return NewKeyValueStore(database, "test")
+}
+
+// TestAddKeyToTransaction Check that a single value is stored after made commit
+func TestKeyValueStoreNewDbAndCommit(t *testing.T) {
+	dbKV := NewKeyValueDb(t.TempDir(), 0)
+	database := setupKvStoreTest(dbKV)
+	database.Begin()
+
+	database.Put([]byte("key"), []byte("value"))
+
+	get, has := database.Get([]byte("key"))
+	if !has || get == nil {
+		t.Fail()
+	}
+
+	if string(get) != "value" {
+		t.Fail()
+	}
+
+	database.Delete([]byte("key"))
+
+	get, has = database.Get([]byte("key"))
+	if has || get != nil {
+		t.Fail()
+	}
+	database.Rollback()
+
+	database.Close()
+}
diff --git a/pkg/db/sortedList.go b/internal/db/sorted_list.go
similarity index 100%
rename from pkg/db/sortedList.go
rename to internal/db/sorted_list.go
diff --git a/pkg/db/sortedList_test.go b/internal/db/sorted_list_test.go
similarity index 100%
rename from pkg/db/sortedList_test.go
rename to internal/db/sorted_list_test.go
diff --git a/pkg/db/state/code.go b/internal/db/state/code.go
similarity index 100%
rename from pkg/db/state/code.go
rename to internal/db/state/code.go
diff --git a/pkg/db/state/code_test.go b/internal/db/state/code_test.go
similarity index 96%
rename from pkg/db/state/code_test.go
rename to internal/db/state/code_test.go
index 6d5a9778..a4122556 100644
--- a/pkg/db/state/code_test.go
+++ b/internal/db/state/code_test.go
@@ -4,7 +4,7 @@ import (
 	"bytes"
 	"embed"
 	"encoding/json"
-	"github.com/NethermindEth/juno/pkg/db"
+	db2 "github.com/NethermindEth/juno/internal/db"
 	"math/big"
 	"testing"
 )
@@ -169,8 +169,8 @@ func TestManager_Code(t *testing.T) {
 		}
 		tests = append(tests, test)
 	}
-	codeDatabase := db.New(t.TempDir(), 0)
-	storageDatabase := db.NewBlockSpecificDatabase(db.New(t.TempDir(), 0))
+	codeDatabase := db2.NewKeyValueDb(t.TempDir(), 0)
+	storageDatabase := db2.NewBlockSpecificDatabase(db2.NewKeyValueDb(t.TempDir(), 0))
 	manager := NewStateManager(codeDatabase, *storageDatabase)
 	for _, test := range tests {
 		var code ContractCode
diff --git a/pkg/db/state/storage.go b/internal/db/state/storage.go
similarity index 100%
rename from pkg/db/state/storage.go
rename to internal/db/state/storage.go
diff --git a/pkg/db/state/storage_test.go b/internal/db/state/storage_test.go
similarity index 96%
rename from pkg/db/state/storage_test.go
rename to internal/db/state/storage_test.go
index bbea90d2..9e879cc4 100644
--- a/pkg/db/state/storage_test.go
+++ b/internal/db/state/storage_test.go
@@ -2,7 +2,7 @@ package state
 
 import (
 	"bytes"
-	"github.com/NethermindEth/juno/pkg/db"
+	db2 "github.com/NethermindEth/juno/internal/db"
 	"math/big"
 	"testing"
 )
@@ -117,8 +117,8 @@ func TestManager_Storage(t *testing.T) {
 			5,
 		},
 	}
-	codeDatabase := db.New(t.TempDir(), 0)
-	storageDatabase := db.NewBlockSpecificDatabase(db.New(t.TempDir(), 0))
+	codeDatabase := db2.NewKeyValueDb(t.TempDir(), 0)
+	storageDatabase := db2.NewBlockSpecificDatabase(db2.NewKeyValueDb(t.TempDir(), 0))
 	manager := NewStateManager(codeDatabase, *storageDatabase)
 	for _, data := range initialData {
 		manager.PutStorage(data.Contract, data.BlockNumber, &data.Storage)
diff --git a/pkg/db/transaction/manager_test.go b/internal/db/transaction/manager_test.go
similarity index 97%
rename from pkg/db/transaction/manager_test.go
rename to internal/db/transaction/manager_test.go
index dbea26a6..0f67243f 100644
--- a/pkg/db/transaction/manager_test.go
+++ b/internal/db/transaction/manager_test.go
@@ -1,7 +1,7 @@
 package transaction
 
 import (
-	"github.com/NethermindEth/juno/pkg/db"
+	"github.com/NethermindEth/juno/internal/db"
 	"math/big"
 	"testing"
 )
@@ -94,7 +94,7 @@ var (
 )
 
 func TestManager_PutTransaction(t *testing.T) {
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	manager := NewManager(database)
 	for _, tx := range invokeTransactions {
 		manager.PutTransaction(tx.AsTransaction())
@@ -106,7 +106,7 @@ func TestManager_PutTransaction(t *testing.T) {
 }
 
 func TestManager_GetTransaction(t *testing.T) {
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	manager := NewManager(database)
 	// Insert all the transactions
 	for _, tx := range invokeTransactions {
diff --git a/internal/db/transaction_db_test.go b/internal/db/transaction_db_test.go
new file mode 100644
index 00000000..5791f1ce
--- /dev/null
+++ b/internal/db/transaction_db_test.go
@@ -0,0 +1,139 @@
+package db
+
+import (
+	"testing"
+)
+
+// setupTransactionDbTest creates a new TransactionDb for Tests
+func setupTransactionDbTest(database Databaser) *TransactionDb {
+	return NewTransactionDb(database.GetEnv())
+}
+
+// TestAddKeyToTransaction Check that a single value is stored after made commit
+func TestInsertKeyOnTransactionDbAndCommit(t *testing.T) {
+	dbKV := NewKeyValueDb(t.TempDir(), 0)
+	dbTest := setupTransactionDbTest(dbKV)
+
+	database := dbTest.Begin()
+
+	_ = database.GetEnv()
+
+	err := database.Put([]byte("key"), []byte("value"))
+
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	err = database.Commit()
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	database = dbTest.Begin()
+
+	get, err := database.Get([]byte("key"))
+	if err != nil || get == nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	if string(get) != "value" {
+		t.Fail()
+	}
+
+	database.Close()
+}
+
+// TestInsertKeyOnTransactionDbAndRollback Check that a single is deleted after a rollback
+func TestInsertKeyOnTransactionDbAndRollback(t *testing.T) {
+	dbKV := NewKeyValueDb(t.TempDir(), 0)
+	dbTest := setupTransactionDbTest(dbKV)
+
+	database := dbTest.Begin()
+
+	numItems, _ := database.NumberOfItems()
+	if numItems != 0 {
+		t.Fail()
+	}
+
+	err := database.Put([]byte("key"), []byte("value"))
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	numItems, _ = database.NumberOfItems()
+	if numItems != 1 {
+		t.Fail()
+	}
+
+	database.Rollback()
+
+	database = dbTest.Begin()
+
+	has, err := database.Has([]byte("key"))
+	if err != nil || has {
+		t.Log(err)
+		t.Fail()
+	}
+
+	numItems, _ = database.NumberOfItems()
+	if numItems != 0 {
+		t.Fail()
+	}
+
+	database.Close()
+}
+
+// TestDeletionOnTransactionDb Check that a key is inserted and deleted properly
+func TestDeletionOnTransactionDb(t *testing.T) {
+	dbKV := NewKeyValueDb(t.TempDir(), 0)
+	dbTest := setupTransactionDbTest(dbKV)
+
+	database := dbTest.Begin()
+
+	err := database.Delete([]byte("not_key"))
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	err = database.Put([]byte("key"), []byte("value"))
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	err = database.Commit()
+	if err != nil {
+		t.Fail()
+		return
+	}
+
+	database = dbTest.Begin()
+
+	err = database.Delete([]byte("key"))
+	if err != nil {
+		t.Log(err)
+		t.Fail()
+	}
+
+	has, err := database.Has([]byte("key"))
+	if err != nil || has {
+		t.Log(err)
+		t.Fail()
+	}
+
+	database.Rollback()
+
+	database = dbTest.Begin()
+	has, err = database.Has([]byte("key"))
+	if err != nil || !has {
+		t.Log(err)
+		t.Fail()
+	}
+
+	database.Close()
+}
diff --git a/internal/services/transactions_test.go b/internal/services/transactions_test.go
index 3007361a..50af4b2e 100644
--- a/internal/services/transactions_test.go
+++ b/internal/services/transactions_test.go
@@ -2,8 +2,8 @@ package services
 
 import (
 	"context"
-	"github.com/NethermindEth/juno/pkg/db"
-	"github.com/NethermindEth/juno/pkg/db/transaction"
+	"github.com/NethermindEth/juno/internal/db"
+	"github.com/NethermindEth/juno/internal/db/transaction"
 	"math/big"
 	"testing"
 )
@@ -97,7 +97,7 @@ var (
 
 func TestTransactionService_StoreTransaction(t *testing.T) {
 	defer resetTransactionService()
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	TransactionService.Setup(database)
 	err := TransactionService.Run()
 	if err != nil {
@@ -115,7 +115,7 @@ func TestTransactionService_StoreTransaction(t *testing.T) {
 
 func TestManager_GetTransaction(t *testing.T) {
 	defer resetTransactionService()
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	TransactionService.Setup(database)
 	err := TransactionService.Run()
 	if err != nil {
@@ -148,7 +148,7 @@ func TestManager_GetTransaction(t *testing.T) {
 // running
 func TestTransactionService_Run(t *testing.T) {
 	defer resetTransactionService()
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	TransactionService.Setup(database)
 	err := TransactionService.Run()
 	if err != nil {
@@ -164,7 +164,7 @@ func TestTransactionService_Run(t *testing.T) {
 // a second run, in both cases, an error should not occur.
 func TestTransactionService_Close(t *testing.T) {
 	defer resetTransactionService()
-	database := db.New(t.TempDir(), 0)
+	database := db.NewKeyValueDb(t.TempDir(), 0)
 	TransactionService.Setup(database)
 	err := TransactionService.Run()
 	if err != nil {