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.
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
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
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
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 ()>,
}