mirror of
https://github.com/serai-dex/serai.git
synced 2025-03-21 06:38:56 +00:00
Correct misc compilation errors
This commit is contained in:
parent
a2717d73f0
commit
2b47feafed
5 changed files with 70 additions and 27 deletions
|
@ -13,9 +13,9 @@ impl<T: BorshSerialize + BorshDeserialize> Borshy for T {}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub(crate) struct SeraiKey<K: Borshy> {
|
pub(crate) struct SeraiKey<K: Borshy> {
|
||||||
activation_block_number: u64,
|
pub(crate) activation_block_number: u64,
|
||||||
retirement_block_number: Option<u64>,
|
pub(crate) retirement_block_number: Option<u64>,
|
||||||
key: K,
|
pub(crate) key: K,
|
||||||
}
|
}
|
||||||
|
|
||||||
create_db!(
|
create_db!(
|
||||||
|
@ -208,7 +208,7 @@ impl<S: ScannerFeed> ScannerDb<S> {
|
||||||
SerializedOutputs::set(txn, block_number, &buf);
|
SerializedOutputs::set(txn, block_number, &buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_notable_block(getter: &impl Get, number: u64) -> bool {
|
pub(crate) fn is_block_notable(getter: &impl Get, number: u64) -> bool {
|
||||||
NotableBlock::get(getter, number).is_some()
|
NotableBlock::get(getter, number).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,21 @@ use primitives::{ReceivedOutput, Block};
|
||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
mod index;
|
mod index;
|
||||||
|
mod scan;
|
||||||
|
mod eventuality;
|
||||||
|
mod report;
|
||||||
|
mod safe;
|
||||||
|
|
||||||
/// A feed usable to scan a blockchain.
|
/// A feed usable to scan a blockchain.
|
||||||
///
|
///
|
||||||
/// This defines the primitive types used, along with various getters necessary for indexing.
|
/// This defines the primitive types used, along with various getters necessary for indexing.
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait ScannerFeed: Send + Sync {
|
pub trait ScannerFeed: Send + Sync {
|
||||||
|
/// The amount of confirmations required for a block to be finalized.
|
||||||
|
///
|
||||||
|
/// This value must be at least `1`.
|
||||||
|
const CONFIRMATIONS: u64;
|
||||||
|
|
||||||
/// The type of the key used to receive coins on this blockchain.
|
/// The type of the key used to receive coins on this blockchain.
|
||||||
type Key: group::Group + group::GroupEncoding;
|
type Key: group::Group + group::GroupEncoding;
|
||||||
|
|
||||||
|
@ -35,11 +44,19 @@ pub trait ScannerFeed: Send + Sync {
|
||||||
/// resolve without manual intervention.
|
/// resolve without manual intervention.
|
||||||
type EphemeralError: Debug;
|
type EphemeralError: Debug;
|
||||||
|
|
||||||
|
/// Fetch the number of the latest block.
|
||||||
|
///
|
||||||
|
/// The block number is its zero-indexed position within a linear view of the external network's
|
||||||
|
/// consensus. The genesis block accordingly has block number 0.
|
||||||
|
async fn latest_block_number(&self) -> Result<u64, Self::EphemeralError>;
|
||||||
|
|
||||||
/// Fetch the number of the latest finalized block.
|
/// Fetch the number of the latest finalized block.
|
||||||
///
|
///
|
||||||
/// The block number is its zero-indexed position within a linear view of the external network's
|
/// The block number is its zero-indexed position within a linear view of the external network's
|
||||||
/// consensus. The genesis block accordingly has block number 0.
|
/// consensus. The genesis block accordingly has block number 0.
|
||||||
async fn latest_finalized_block_number(&self) -> Result<u64, Self::EphemeralError>;
|
async fn latest_finalized_block_number(&self) -> Result<u64, Self::EphemeralError> {
|
||||||
|
Ok(self.latest_block_number().await? - Self::CONFIRMATIONS)
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch a block by its number.
|
/// Fetch a block by its number.
|
||||||
async fn block_by_number(&self, number: u64) -> Result<Self::Block, Self::EphemeralError>;
|
async fn block_by_number(&self, number: u64) -> Result<Self::Block, Self::EphemeralError>;
|
||||||
|
@ -49,7 +66,7 @@ pub trait ScannerFeed: Send + Sync {
|
||||||
&self,
|
&self,
|
||||||
block: &Self::Block,
|
block: &Self::Block,
|
||||||
key: Self::Key,
|
key: Self::Key,
|
||||||
) -> Result<Self::Output, Self::EphemeralError>;
|
) -> Result<Vec<Self::Output>, Self::EphemeralError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A handle to immediately run an iteration of a task.
|
/// A handle to immediately run an iteration of a task.
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serai_db::{Db, DbTxn};
|
||||||
use primitives::{Id, Block};
|
use primitives::{Id, Block};
|
||||||
|
|
||||||
// TODO: Localize to ReportDb?
|
// TODO: Localize to ReportDb?
|
||||||
use crate::{db::ScannerDb, ScannerFeed};
|
use crate::{db::ScannerDb, ScannerFeed, ContinuallyRan};
|
||||||
|
|
||||||
struct ReportTask<D: Db, S: ScannerFeed> {
|
struct ReportTask<D: Db, S: ScannerFeed> {
|
||||||
db: D,
|
db: D,
|
||||||
|
@ -20,8 +20,10 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for ReportTask<D, S> {
|
||||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||||
let highest_reportable = {
|
let highest_reportable = {
|
||||||
// Fetch the latest scanned and latest checked block
|
// Fetch the latest scanned and latest checked block
|
||||||
let next_to_scan = ScannerDb::<S>::next_to_scan_for_outputs_block(&self.db).expect("ReportTask run before writing the start block");
|
let next_to_scan = ScannerDb::<S>::next_to_scan_for_outputs_block(&self.db)
|
||||||
let next_to_check = ScannerDb::<S>::next_to_check_for_eventualities_block(&self.db).expect("ReportTask run before writing the start block");
|
.expect("ReportTask run before writing the start block");
|
||||||
|
let next_to_check = ScannerDb::<S>::next_to_check_for_eventualities_block(&self.db)
|
||||||
|
.expect("ReportTask run before writing the start block");
|
||||||
// If we haven't done any work, return
|
// If we haven't done any work, return
|
||||||
if (next_to_scan == 0) || (next_to_check == 0) {
|
if (next_to_scan == 0) || (next_to_check == 0) {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
@ -31,10 +33,11 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for ReportTask<D, S> {
|
||||||
last_scanned.min(last_checked)
|
last_scanned.min(last_checked)
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_to_potentially_report = ScannerDb::<S>::next_block_to_potentially_report(&self.db).expect("ReportTask run before writing the start block");
|
let next_to_potentially_report = ScannerDb::<S>::next_to_potentially_report_block(&self.db)
|
||||||
|
.expect("ReportTask run before writing the start block");
|
||||||
|
|
||||||
for b in next_to_potentially_report ..= highest_reportable {
|
for b in next_to_potentially_report ..= highest_reportable {
|
||||||
if ScannerDb::<S>::is_block_notable(b) {
|
if ScannerDb::<S>::is_block_notable(&self.db, b) {
|
||||||
todo!("TODO: Make Batches, which requires handling Forwarded within this crate");
|
todo!("TODO: Make Batches, which requires handling Forwarded within this crate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use serai_db::{Db, DbTxn};
|
||||||
use primitives::{Id, Block};
|
use primitives::{Id, Block};
|
||||||
|
|
||||||
// TODO: Localize to SafeDb?
|
// TODO: Localize to SafeDb?
|
||||||
use crate::{db::ScannerDb, ScannerFeed};
|
use crate::{db::ScannerDb, ScannerFeed, ContinuallyRan};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We mark blocks safe to scan when they're no more than `(CONFIRMATIONS - 1)` blocks after the
|
We mark blocks safe to scan when they're no more than `(CONFIRMATIONS - 1)` blocks after the
|
||||||
|
@ -27,7 +27,8 @@ struct SafeToScanTask<D: Db, S: ScannerFeed> {
|
||||||
impl<D: Db, S: ScannerFeed> ContinuallyRan for SafeToScanTask<D, S> {
|
impl<D: Db, S: ScannerFeed> ContinuallyRan for SafeToScanTask<D, S> {
|
||||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||||
// First, we fetch the highest acknowledged block
|
// First, we fetch the highest acknowledged block
|
||||||
let Some(highest_acknowledged_block) = ScannerDb::<S>::highest_acknowledged_block(&self.db) else {
|
let Some(highest_acknowledged_block) = ScannerDb::<S>::highest_acknowledged_block(&self.db)
|
||||||
|
else {
|
||||||
// If no blocks have been acknowledged, we don't mark any safe
|
// If no blocks have been acknowledged, we don't mark any safe
|
||||||
// Once the start block (implicitly safe) has been acknowledged, we proceed from there
|
// Once the start block (implicitly safe) has been acknowledged, we proceed from there
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
@ -38,13 +39,15 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SafeToScanTask<D, S> {
|
||||||
// If we've decided to report (or not report) a block, we know if it needs acknowledgement
|
// If we've decided to report (or not report) a block, we know if it needs acknowledgement
|
||||||
// (and accordingly is pending acknowledgement)
|
// (and accordingly is pending acknowledgement)
|
||||||
// Accordingly, the block immediately before this is the latest block with a known status
|
// Accordingly, the block immediately before this is the latest block with a known status
|
||||||
ScannerDb::<S>::next_block_to_potentially_report(&self.db).expect("SafeToScanTask run before writing the start block") - 1
|
ScannerDb::<S>::next_to_potentially_report_block(&self.db)
|
||||||
|
.expect("SafeToScanTask run before writing the start block") -
|
||||||
|
1
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut oldest_pending_acknowledgement = None;
|
let mut oldest_pending_acknowledgement = None;
|
||||||
for b in (highest_acknowledged_block + 1) ..= latest_block_known_if_pending_acknowledgement {
|
for b in (highest_acknowledged_block + 1) ..= latest_block_known_if_pending_acknowledgement {
|
||||||
// If the block isn't notable, immediately flag it as acknowledged
|
// If the block isn't notable, immediately flag it as acknowledged
|
||||||
if !ScannerDb::<S>::is_block_notable(b) {
|
if !ScannerDb::<S>::is_block_notable(&self.db, b) {
|
||||||
let mut txn = self.db.txn();
|
let mut txn = self.db.txn();
|
||||||
ScannerDb::<S>::set_highest_acknowledged_block(&mut txn, b);
|
ScannerDb::<S>::set_highest_acknowledged_block(&mut txn, b);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
@ -61,13 +64,19 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SafeToScanTask<D, S> {
|
||||||
// acknowledgement, and the oldest block still pending acknowledgement is in the future,
|
// acknowledgement, and the oldest block still pending acknowledgement is in the future,
|
||||||
// we know the safe block to scan to is
|
// we know the safe block to scan to is
|
||||||
// `>= latest_block_known_if_pending_acknowledgement + (CONFIRMATIONS - 1)`
|
// `>= latest_block_known_if_pending_acknowledgement + (CONFIRMATIONS - 1)`
|
||||||
let oldest_pending_acknowledgement = oldest_pending_acknowledgement.unwrap_or(latest_block_known_if_pending_acknowledgement);
|
let oldest_pending_acknowledgement =
|
||||||
|
oldest_pending_acknowledgement.unwrap_or(latest_block_known_if_pending_acknowledgement);
|
||||||
|
|
||||||
|
let old_safe_block = ScannerDb::<S>::latest_scannable_block(&self.db)
|
||||||
|
.expect("SafeToScanTask run before writing the start block");
|
||||||
|
let new_safe_block = oldest_pending_acknowledgement +
|
||||||
|
(S::CONFIRMATIONS.checked_sub(1).expect("CONFIRMATIONS wasn't at least 1"));
|
||||||
|
|
||||||
// Update the latest scannable block
|
// Update the latest scannable block
|
||||||
let mut txn = self.db.txn();
|
let mut txn = self.db.txn();
|
||||||
ScannerDb::<S>::set_latest_scannable_block(oldest_pending_acknowledgement + (CONFIRMATIONS - 1));
|
ScannerDb::<S>::set_latest_scannable_block(&mut txn, new_safe_block);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
Ok(next_to_potentially_report <= highest_reportable)
|
Ok(old_safe_block != new_safe_block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use serai_db::{Db, DbTxn};
|
use serai_db::{Db, DbTxn};
|
||||||
|
|
||||||
use primitives::{Id, Block};
|
use primitives::{Id, ReceivedOutput, Block};
|
||||||
|
|
||||||
// TODO: Localize to ScanDb?
|
// TODO: Localize to ScanDb?
|
||||||
use crate::{db::ScannerDb, ScannerFeed};
|
use crate::{db::ScannerDb, ScannerFeed, ContinuallyRan};
|
||||||
|
|
||||||
struct ScanForOutputsTask<D: Db, S: ScannerFeed> {
|
struct ScanForOutputsTask<D: Db, S: ScannerFeed> {
|
||||||
db: D,
|
db: D,
|
||||||
|
@ -14,9 +14,11 @@ struct ScanForOutputsTask<D: Db, S: ScannerFeed> {
|
||||||
impl<D: Db, S: ScannerFeed> ContinuallyRan for ScanForOutputsTask<D, S> {
|
impl<D: Db, S: ScannerFeed> ContinuallyRan for ScanForOutputsTask<D, S> {
|
||||||
async fn run_iteration(&mut self) -> Result<bool, String> {
|
async fn run_iteration(&mut self) -> Result<bool, String> {
|
||||||
// Fetch the safe to scan block
|
// Fetch the safe to scan block
|
||||||
let latest_scannable = ScannerDb::<S>::latest_scannable_block(&self.db).expect("ScanForOutputsTask run before writing the start block");
|
let latest_scannable = ScannerDb::<S>::latest_scannable_block(&self.db)
|
||||||
|
.expect("ScanForOutputsTask run before writing the start block");
|
||||||
// Fetch the next block to scan
|
// Fetch the next block to scan
|
||||||
let next_to_scan = ScannerDb::<S>::next_to_scan_for_outputs_block(&self.db).expect("ScanForOutputsTask run before writing the start block");
|
let next_to_scan = ScannerDb::<S>::next_to_scan_for_outputs_block(&self.db)
|
||||||
|
.expect("ScanForOutputsTask run before writing the start block");
|
||||||
|
|
||||||
for b in next_to_scan ..= latest_scannable {
|
for b in next_to_scan ..= latest_scannable {
|
||||||
let block = match self.feed.block_by_number(b).await {
|
let block = match self.feed.block_by_number(b).await {
|
||||||
|
@ -26,15 +28,22 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for ScanForOutputsTask<D, S> {
|
||||||
|
|
||||||
// Check the ID of this block is the expected ID
|
// Check the ID of this block is the expected ID
|
||||||
{
|
{
|
||||||
let expected = ScannerDb::<S>::block_id(b).expect("scannable block didn't have its ID saved");
|
let expected =
|
||||||
|
ScannerDb::<S>::block_id(&self.db, b).expect("scannable block didn't have its ID saved");
|
||||||
if block.id() != expected {
|
if block.id() != expected {
|
||||||
panic!("finalized chain reorganized from {} to {} at {}", hex::encode(expected), hex::encode(block.id()), b);
|
panic!(
|
||||||
|
"finalized chain reorganized from {} to {} at {}",
|
||||||
|
hex::encode(expected),
|
||||||
|
hex::encode(block.id()),
|
||||||
|
b
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("scanning block: {} ({b})", hex::encode(block.id()));
|
log::info!("scanning block: {} ({b})", hex::encode(block.id()));
|
||||||
|
|
||||||
let keys = ScannerDb::<S>::keys(&self.db).expect("scanning for a blockchain without any keys set");
|
let mut keys =
|
||||||
|
ScannerDb::<S>::keys(&self.db).expect("scanning for a blockchain without any keys set");
|
||||||
// Remove all the retired keys
|
// Remove all the retired keys
|
||||||
while let Some(retire_at) = keys[0].retirement_block_number {
|
while let Some(retire_at) = keys[0].retirement_block_number {
|
||||||
if retire_at <= b {
|
if retire_at <= b {
|
||||||
|
@ -51,8 +60,13 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for ScanForOutputsTask<D, S> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for output in network.scan_for_outputs(&block, key).awaits {
|
for output in self
|
||||||
assert_eq!(output.key(), key);
|
.feed
|
||||||
|
.scan_for_outputs(&block, key.key.0)
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("failed to scan block {b}: {e:?}"))?
|
||||||
|
{
|
||||||
|
assert_eq!(output.key(), key.key.0);
|
||||||
// TODO: Check for dust
|
// TODO: Check for dust
|
||||||
outputs.push(output);
|
outputs.push(output);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue