Try   HackMD

PR: https://github.com/sigp/lighthouse/pull/4529

Currently the Lighthouse slasher backend supports two different database implementations; lmdb and mdbx. I am currently working on adding a redb implementation. Redb is a simple, portable, high-performance, ACID, embedded key-value store. Lmdb, Mdbx and Redb share many similarities. However there are some differences with redb that are important to note, especially in the context of the existing slasher backend.

Database Tables

Lmdb and Mdbx do not have a concept of database tables. For these two implementations we end up creating 9 separate database instances within the slasher backend.

However, Redb introduces the concept of database tables. Therefore, for this implementation, its probably not necessary to create separate database instances. We can instead create one database instance, and 9 tables contained within that instance.

We still need the redb implementation to support the existing OpenDatabases interface so I've defined a Database struct as follows:

pub struct Database<'env> {
    table: &'env str
}

Each instance of Database would store the filepath to the relevant table.

Tables can be opened in read mode, or read write mode. Its also important to pass in a Table Definition when opening a database table. See redb_impl.rs for more details

Database Environment

Lmdb and Mdbx introduce the concept of a database environment. There is no such concept in Redb. However the slasher backend implementation in Lighthouse does rely on an Environment struct. For the redb implementation ive defined this struct as:

pub struct Environment {
    env: PathBuf,
}

where env would be initialized as the database path fetched from the config

Database Cursor

Lmdb and Mdbx have built in functionality for a database cursor. This does not exist in Redb. In order to recreate this functionality I created a Cursor struct

pub struct Cursor<'env> {
    db: &'env Database<'env>,
    current_key: Option<Cow<'env, [u8]>>
}

Where current_key stores the key that our cursor is currently pointed to. See redb_impl.rs for more details

Database RwTransaction

Initially my plan was create a RwTransaction struct as follows

pub struct RwTransaction<'env> {
    txn: Option<WriteTransaction<'env>>,
}

Where WriteTransaction is a newtype wrapper around redb::WriteTransaction

pub struct WriteTransaction<'env>(redb::WriteTransaction<'env>);

This was needed since redb::WriteTransaction does not implement the debug trait.

However there were some lifetime issues that I'm having a hard time resolving. So for now I have RwTranasction as follows:

pub struct RwTransaction<'env> {
    _phantom:  PhantomData<&'env ()>,
}