Redb slasher backend impl (#4529)

* initial redb impl

* redb impl

* remove phantom data

* fixed table definition

* fighting the borrow checker

* a rough draft that doesnt cause lifetime issues

* refactoring

* refactor

* refactor

* passing unit tests

* refactor

* refactor

* refactor

* commit

* move everything to one database

* remove panics, ready for a review

* merge

* a working redb impl

* passing a ref of txn to cursor

* this tries to create a second write transaction when initializing cursor. breaks everything

* Use 2 lifetimes and subtyping

Also fixes a bug in last_key caused by rev and next_back cancelling out

* Move table into cursor

* Merge remote-tracking branch 'origin/unstable' into redb-slasher-backend-impl

* changes based on feedback

* update lmdb

* fix lifetime issues

* moving everything from Cursor to Transaction

* update

* upgrade to redb 2.0

* Merge branch 'unstable' of https://github.com/sigp/lighthouse into redb-slasher-backend-impl

* bring back cursor

* Merge branch 'unstable' of https://github.com/sigp/lighthouse into redb-slasher-backend-impl

* fix delete while

* linting

* linting

* switch to lmdb

* update redb to v2.1

* build fixes, remove unwrap or default

* another build error

* hopefully this is the last build error

* fmt

* cargo.toml

* fix mdbx

* Merge branch 'unstable' of https://github.com/sigp/lighthouse into redb-slasher-backend-impl

* Remove a collect

* Merge remote-tracking branch 'origin/unstable' into redb-slasher-backend-impl

* Merge branch 'redb-slasher-backend-impl' of https://github.com/eserilev/lighthouse into redb-slasher-backend-impl

* re-enable test

* fix failing slasher test

* Merge remote-tracking branch 'origin/unstable' into redb-slasher-backend-impl

* Rename DB file to `slasher.redb`
This commit is contained in:
Eitan Seri-Levi
2024-07-01 03:36:40 +02:00
committed by GitHub
parent 16b81132ca
commit 70bcba1e6b
18 changed files with 499 additions and 72 deletions

View File

@@ -1,6 +1,7 @@
pub mod interface;
mod lmdb_impl;
mod mdbx_impl;
mod redb_impl;
use crate::{
metrics, AttesterRecord, AttesterSlashingStatus, CompactAttesterRecord, Config, Error,
@@ -489,8 +490,7 @@ impl<E: EthSpec> SlasherDB<E> {
}
// Store the new indexed attestation at the end of the current table.
let db = &self.databases.indexed_attestation_db;
let mut cursor = txn.cursor(db)?;
let mut cursor = txn.cursor(&self.databases.indexed_attestation_db)?;
let indexed_att_id = match cursor.last_key()? {
// First ID is 1 so that 0 can be used to represent `null` in `CompactAttesterRecord`.
@@ -504,7 +504,6 @@ impl<E: EthSpec> SlasherDB<E> {
cursor.put(attestation_key.as_ref(), &data)?;
drop(cursor);
// Update the (epoch, hash) to ID mapping.
self.put_indexed_attestation_id(txn, &id_key, attestation_key)?;
@@ -743,21 +742,17 @@ impl<E: EthSpec> SlasherDB<E> {
return Ok(());
}
loop {
let (key_bytes, _) = cursor.get_current()?.ok_or(Error::MissingProposerKey)?;
let (slot, _) = ProposerKey::parse(key_bytes)?;
let should_delete = |key: &[u8]| -> Result<bool, Error> {
let mut should_delete = false;
let (slot, _) = ProposerKey::parse(Cow::from(key))?;
if slot < min_slot {
cursor.delete_current()?;
// End the loop if there is no next entry.
if cursor.next_key()?.is_none() {
break;
}
} else {
break;
should_delete = true;
}
}
Ok(should_delete)
};
cursor.delete_while(should_delete)?;
Ok(())
}
@@ -771,9 +766,6 @@ impl<E: EthSpec> SlasherDB<E> {
.saturating_add(1u64)
.saturating_sub(self.config.history_length as u64);
// Collect indexed attestation IDs to delete.
let mut indexed_attestation_ids = vec![];
let mut cursor = txn.cursor(&self.databases.indexed_attestation_id_db)?;
// Position cursor at first key, bailing out if the database is empty.
@@ -781,27 +773,20 @@ impl<E: EthSpec> SlasherDB<E> {
return Ok(());
}
loop {
let (key_bytes, value) = cursor
.get_current()?
.ok_or(Error::MissingIndexedAttestationIdKey)?;
let (target_epoch, _) = IndexedAttestationIdKey::parse(key_bytes)?;
let should_delete = |key: &[u8]| -> Result<bool, Error> {
let (target_epoch, _) = IndexedAttestationIdKey::parse(Cow::from(key))?;
if target_epoch < min_epoch {
indexed_attestation_ids.push(IndexedAttestationId::new(
IndexedAttestationId::parse(value)?,
));
cursor.delete_current()?;
if cursor.next_key()?.is_none() {
break;
}
} else {
break;
return Ok(true);
}
}
Ok(false)
};
let indexed_attestation_ids = cursor
.delete_while(should_delete)?
.into_iter()
.map(|id| IndexedAttestationId::parse(id).map(IndexedAttestationId::new))
.collect::<Result<Vec<IndexedAttestationId>, Error>>()?;
drop(cursor);
// Delete the indexed attestations.