Make a dedicated IndexDb

This commit is contained in:
Luke Parker 2024-08-26 23:24:49 -04:00
parent 66f3428051
commit 1e8f4e6156
4 changed files with 47 additions and 34 deletions

View file

@ -44,13 +44,8 @@ impl<S: ScannerFeed> OutputWithInInstruction<S> {
create_db!( create_db!(
Scanner { Scanner {
BlockId: (number: u64) -> [u8; 32],
BlockNumber: (id: [u8; 32]) -> u64,
ActiveKeys: <K: Borshy>() -> Vec<SeraiKeyDbEntry<K>>, ActiveKeys: <K: Borshy>() -> Vec<SeraiKeyDbEntry<K>>,
// The latest finalized block to appear of a blockchain
LatestFinalizedBlock: () -> u64,
// The next block to scan for received outputs // The next block to scan for received outputs
NextToScanForOutputsBlock: () -> u64, NextToScanForOutputsBlock: () -> u64,
// The next block to check for resolving eventualities // The next block to check for resolving eventualities
@ -89,17 +84,6 @@ create_db!(
pub(crate) struct ScannerDb<S: ScannerFeed>(PhantomData<S>); pub(crate) struct ScannerDb<S: ScannerFeed>(PhantomData<S>);
impl<S: ScannerFeed> ScannerDb<S> { impl<S: ScannerFeed> ScannerDb<S> {
pub(crate) fn set_block(txn: &mut impl DbTxn, number: u64, id: [u8; 32]) {
BlockId::set(txn, number, &id);
BlockNumber::set(txn, id, &number);
}
pub(crate) fn block_id(getter: &impl Get, number: u64) -> Option<[u8; 32]> {
BlockId::get(getter, number)
}
pub(crate) fn block_number(getter: &impl Get, id: [u8; 32]) -> Option<u64> {
BlockNumber::get(getter, id)
}
// activation_block_number is inclusive, so the key will be scanned for starting at the specified // activation_block_number is inclusive, so the key will be scanned for starting at the specified
// block // block
pub(crate) fn queue_key(txn: &mut impl DbTxn, activation_block_number: u64, key: KeyFor<S>) { pub(crate) fn queue_key(txn: &mut impl DbTxn, activation_block_number: u64, key: KeyFor<S>) {
@ -155,13 +139,13 @@ impl<S: ScannerFeed> ScannerDb<S> {
pub(crate) fn set_start_block(txn: &mut impl DbTxn, start_block: u64, id: [u8; 32]) { pub(crate) fn set_start_block(txn: &mut impl DbTxn, start_block: u64, id: [u8; 32]) {
assert!( assert!(
LatestFinalizedBlock::get(txn).is_none(), NextToScanForOutputsBlock::get(txn).is_none(),
"setting start block but prior set start block" "setting start block but prior set start block"
); );
Self::set_block(txn, start_block, id); crate::index::IndexDb::set_block(txn, start_block, id);
crate::index::IndexDb::set_latest_finalized_block(txn, start_block);
LatestFinalizedBlock::set(txn, &start_block);
NextToScanForOutputsBlock::set(txn, &start_block); NextToScanForOutputsBlock::set(txn, &start_block);
// We can receive outputs in this block, but any descending transactions will be in the next // We can receive outputs in this block, but any descending transactions will be in the next
// block. This, with the check on-set, creates a bound that this value in the DB is non-zero. // block. This, with the check on-set, creates a bound that this value in the DB is non-zero.
@ -169,13 +153,6 @@ impl<S: ScannerFeed> ScannerDb<S> {
NextToPotentiallyReportBlock::set(txn, &start_block); NextToPotentiallyReportBlock::set(txn, &start_block);
} }
pub(crate) fn set_latest_finalized_block(txn: &mut impl DbTxn, latest_finalized_block: u64) {
LatestFinalizedBlock::set(txn, &latest_finalized_block);
}
pub(crate) fn latest_finalized_block(getter: &impl Get) -> Option<u64> {
LatestFinalizedBlock::get(getter)
}
pub(crate) fn latest_scannable_block(getter: &impl Get) -> Option<u64> { pub(crate) fn latest_scannable_block(getter: &impl Get) -> Option<u64> {
// We can only scan up to whatever block we've checked the Eventualities of, plus the window // We can only scan up to whatever block we've checked the Eventualities of, plus the window
// length. Since this returns an inclusive bound, we need to subtract 1 // length. Since this returns an inclusive bound, we need to subtract 1

View file

@ -0,0 +1,34 @@
use serai_db::{Get, DbTxn, create_db};
create_db!(
ScannerIndex {
// A lookup of a block's number to its ID
BlockId: (number: u64) -> [u8; 32],
// A lookup of a block's ID to its number
BlockNumber: (id: [u8; 32]) -> u64,
// The latest finalized block to appear on the blockchain
LatestFinalizedBlock: () -> u64,
}
);
pub(crate) struct IndexDb;
impl IndexDb {
pub(crate) fn set_block(txn: &mut impl DbTxn, number: u64, id: [u8; 32]) {
BlockId::set(txn, number, &id);
BlockNumber::set(txn, id, &number);
}
pub(crate) fn block_id(getter: &impl Get, number: u64) -> Option<[u8; 32]> {
BlockId::get(getter, number)
}
pub(crate) fn block_number(getter: &impl Get, id: [u8; 32]) -> Option<u64> {
BlockNumber::get(getter, id)
}
pub(crate) fn set_latest_finalized_block(txn: &mut impl DbTxn, latest_finalized_block: u64) {
LatestFinalizedBlock::set(txn, &latest_finalized_block);
}
pub(crate) fn latest_finalized_block(getter: &impl Get) -> Option<u64> {
LatestFinalizedBlock::get(getter)
}
}

View file

@ -1,9 +1,11 @@
use serai_db::{DbTxn, Db}; use serai_db::{DbTxn, Db};
use primitives::BlockHeader; use primitives::{task::ContinuallyRan, BlockHeader};
// TODO: Localize to IndexDb? use crate::ScannerFeed;
use crate::{db::ScannerDb, ScannerFeed, ContinuallyRan};
mod db;
pub(crate) use db::IndexDb;
/* /*
This processor should build its own index of the blockchain, yet only for finalized blocks which This processor should build its own index of the blockchain, yet only for finalized blocks which
@ -22,7 +24,7 @@ struct IndexFinalizedTask<D: Db, S: ScannerFeed> {
impl<D: Db, S: ScannerFeed> ContinuallyRan for IndexFinalizedTask<D, S> { impl<D: Db, S: ScannerFeed> ContinuallyRan for IndexFinalizedTask<D, S> {
async fn run_iteration(&mut self) -> Result<bool, String> { async fn run_iteration(&mut self) -> Result<bool, String> {
// Fetch the latest finalized block // Fetch the latest finalized block
let our_latest_finalized = ScannerDb::<S>::latest_finalized_block(&self.db) let our_latest_finalized = IndexDb::latest_finalized_block(&self.db)
.expect("IndexTask run before writing the start block"); .expect("IndexTask run before writing the start block");
let latest_finalized = match self.feed.latest_finalized_block_number().await { let latest_finalized = match self.feed.latest_finalized_block_number().await {
Ok(latest_finalized) => latest_finalized, Ok(latest_finalized) => latest_finalized,
@ -51,7 +53,7 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for IndexFinalizedTask<D, S> {
// Check this descends from our indexed chain // Check this descends from our indexed chain
{ {
let expected_parent = let expected_parent =
ScannerDb::<S>::block_id(&self.db, b - 1).expect("didn't have the ID of the prior block"); IndexDb::block_id(&self.db, b - 1).expect("didn't have the ID of the prior block");
if block.parent() != expected_parent { if block.parent() != expected_parent {
panic!( panic!(
"current finalized block (#{b}, {}) doesn't build off finalized block (#{}, {})", "current finalized block (#{b}, {}) doesn't build off finalized block (#{}, {})",
@ -64,8 +66,8 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for IndexFinalizedTask<D, S> {
// Update the latest finalized block // Update the latest finalized block
let mut txn = self.db.txn(); let mut txn = self.db.txn();
ScannerDb::<S>::set_block(&mut txn, b, block.id()); IndexDb::set_block(&mut txn, b, block.id());
ScannerDb::<S>::set_latest_finalized_block(&mut txn, b); IndexDb::set_latest_finalized_block(&mut txn, b);
txn.commit(); txn.commit();
} }

View file

@ -112,7 +112,7 @@ pub trait ScannerFeed: Send + Sync {
// Check the ID of this block is the expected ID // Check the ID of this block is the expected ID
{ {
let expected = let expected =
ScannerDb::<S>::block_id(&self.db, number).expect("requested a block which wasn't indexed"); crate::index::IndexDb::block_id(&self.db, number).expect("requested a block which wasn't indexed");
if block.id() != expected { if block.id() != expected {
panic!( panic!(
"finalized chain reorganized from {} to {} at {}", "finalized chain reorganized from {} to {} at {}",