mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Add bounds for the eventuality task
This commit is contained in:
@@ -33,6 +33,8 @@ create_db!(
|
|||||||
NextToCheckForEventualitiesBlock: () -> u64,
|
NextToCheckForEventualitiesBlock: () -> u64,
|
||||||
// The next block to potentially report
|
// The next block to potentially report
|
||||||
NextToPotentiallyReportBlock: () -> u64,
|
NextToPotentiallyReportBlock: () -> u64,
|
||||||
|
// Highest acknowledged block
|
||||||
|
HighestAcknowledgedBlock: () -> u64,
|
||||||
|
|
||||||
// If a block was notable
|
// If a block was notable
|
||||||
/*
|
/*
|
||||||
@@ -122,7 +124,9 @@ impl<S: ScannerFeed> ScannerDb<S> {
|
|||||||
Self::set_block(txn, start_block, id);
|
Self::set_block(txn, start_block, id);
|
||||||
LatestFinalizedBlock::set(txn, &start_block);
|
LatestFinalizedBlock::set(txn, &start_block);
|
||||||
NextToScanForOutputsBlock::set(txn, &start_block);
|
NextToScanForOutputsBlock::set(txn, &start_block);
|
||||||
NextToCheckForEventualitiesBlock::set(txn, &start_block);
|
// 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.
|
||||||
|
NextToCheckForEventualitiesBlock::set(txn, &(start_block + 1));
|
||||||
NextToPotentiallyReportBlock::set(txn, &start_block);
|
NextToPotentiallyReportBlock::set(txn, &start_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,6 +157,10 @@ impl<S: ScannerFeed> ScannerDb<S> {
|
|||||||
txn: &mut impl DbTxn,
|
txn: &mut impl DbTxn,
|
||||||
next_to_check_for_eventualities_block: u64,
|
next_to_check_for_eventualities_block: u64,
|
||||||
) {
|
) {
|
||||||
|
assert!(
|
||||||
|
next_to_check_for_eventualities_block != 0,
|
||||||
|
"next to check for eventualities block was 0 when it's bound non-zero"
|
||||||
|
);
|
||||||
NextToCheckForEventualitiesBlock::set(txn, &next_to_check_for_eventualities_block);
|
NextToCheckForEventualitiesBlock::set(txn, &next_to_check_for_eventualities_block);
|
||||||
}
|
}
|
||||||
pub(crate) fn next_to_check_for_eventualities_block(getter: &impl Get) -> Option<u64> {
|
pub(crate) fn next_to_check_for_eventualities_block(getter: &impl Get) -> Option<u64> {
|
||||||
@@ -169,6 +177,16 @@ impl<S: ScannerFeed> ScannerDb<S> {
|
|||||||
NextToPotentiallyReportBlock::get(getter)
|
NextToPotentiallyReportBlock::get(getter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_highest_acknowledged_block(
|
||||||
|
txn: &mut impl DbTxn,
|
||||||
|
highest_acknowledged_block: u64,
|
||||||
|
) {
|
||||||
|
HighestAcknowledgedBlock::set(txn, &highest_acknowledged_block);
|
||||||
|
}
|
||||||
|
pub(crate) fn highest_acknowledged_block(getter: &impl Get) -> Option<u64> {
|
||||||
|
HighestAcknowledgedBlock::get(getter)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn set_outputs(txn: &mut impl DbTxn, block_number: u64, outputs: Vec<OutputFor<S>>) {
|
pub(crate) fn set_outputs(txn: &mut impl DbTxn, block_number: u64, outputs: Vec<OutputFor<S>>) {
|
||||||
if outputs.is_empty() {
|
if outputs.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
// TODO
|
use serai_db::{Db, DbTxn};
|
||||||
|
|
||||||
|
use primitives::{Id, ReceivedOutput, Block};
|
||||||
|
|
||||||
|
// TODO: Localize to EventualityDb?
|
||||||
|
use crate::{db::ScannerDb, ScannerFeed, ContinuallyRan};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: The following assumes there's some value, `CONFIRMATIONS`, and the finalized block we
|
Note: The following assumes there's some value, `CONFIRMATIONS`, and the finalized block we
|
||||||
@@ -48,3 +53,71 @@
|
|||||||
This forms a backlog only if the latency of scanning, acknowledgement, and intake (including
|
This forms a backlog only if the latency of scanning, acknowledgement, and intake (including
|
||||||
checking Eventualities) exceeds the window duration (the desired property).
|
checking Eventualities) exceeds the window duration (the desired property).
|
||||||
*/
|
*/
|
||||||
|
struct EventualityTask<D: Db, S: ScannerFeed> {
|
||||||
|
db: D,
|
||||||
|
feed: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl<D: Db, S: ScannerFeed> ContinuallyRan for EventualityTask<D, S> {
|
||||||
|
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||||
|
/*
|
||||||
|
The set of Eventualities only increase when a block is acknowledged. Accordingly, we can only
|
||||||
|
iterate up to (and including) the block currently pending acknowledgement. "including" is
|
||||||
|
because even if block `b` causes new Eventualities, they'll only potentially resolve in block
|
||||||
|
`b + 1`.
|
||||||
|
|
||||||
|
We only know blocks will need acknowledgement *for sure* if they were scanned. The only other
|
||||||
|
causes are key activation and retirement (both scheduled outside the scan window). This makes
|
||||||
|
the exclusive upper bound the *next block to scan*.
|
||||||
|
*/
|
||||||
|
let exclusive_upper_bound = {
|
||||||
|
// Fetch the next to scan block
|
||||||
|
let next_to_scan = ScannerDb::<S>::next_to_scan_for_outputs_block(&self.db)
|
||||||
|
.expect("EventualityTask run before writing the start block");
|
||||||
|
// If we haven't done any work, return
|
||||||
|
if next_to_scan == 0 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
next_to_scan
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch the highest acknowledged block
|
||||||
|
let highest_acknowledged = ScannerDb::<S>::highest_acknowledged_block(&self.db)
|
||||||
|
.expect("EventualityTask run before writing the start block");
|
||||||
|
|
||||||
|
// Fetch the next block to check
|
||||||
|
let next_to_check = ScannerDb::<S>::next_to_check_for_eventualities_block(&self.db)
|
||||||
|
.expect("EventualityTask run before writing the start block");
|
||||||
|
|
||||||
|
// Check all blocks
|
||||||
|
let mut iterated = false;
|
||||||
|
for b in next_to_check .. exclusive_upper_bound {
|
||||||
|
// If the prior block was notable *and* not acknowledged, break
|
||||||
|
// This is so if it caused any Eventualities (which may resolve this block), we have them
|
||||||
|
{
|
||||||
|
// This `- 1` is safe as next to check is bound to be non-zero
|
||||||
|
// This is possible since even if we receive coins in block 0, any transactions we'd make
|
||||||
|
// would resolve in block 1 (the first block we'll check under this non-zero rule)
|
||||||
|
let prior_block = b - 1;
|
||||||
|
if ScannerDb::<S>::is_block_notable(&self.db, prior_block) &&
|
||||||
|
(prior_block > highest_acknowledged)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iterated = true;
|
||||||
|
|
||||||
|
todo!("TODO");
|
||||||
|
|
||||||
|
let mut txn = self.db.txn();
|
||||||
|
// Update the next to check block
|
||||||
|
ScannerDb::<S>::set_next_to_check_for_eventualities_block(&mut txn, next_to_check);
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run dependents if we successfully checked any blocks
|
||||||
|
Ok(iterated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user