Allow scheduler's creation of transactions to be async and error

I don't love this, but it's the only way to select decoys without using a local
database. While the prior commit added such a databse, the performance of it
presumably wasn't viable, and while TODOs marked the needed improvements, it
was still messy with an immense scope re: any auditing.

The relevant scheduler functions now take `&self` (intentional, as all
mutations should be via the `&mut impl DbTxn` passed). The calls to `&self` are
expected to be completely deterministic (as usual).
This commit is contained in:
Luke Parker
2024-09-14 01:09:35 -04:00
parent 2edc2f3612
commit e1ad897f7e
11 changed files with 723 additions and 854 deletions

View File

@@ -5,7 +5,6 @@ use monero_simple_request_rpc::SimpleRequestRpc;
use serai_client::primitives::{NetworkId, Coin, Amount};
use serai_db::Db;
use scanner::ScannerFeed;
use signers::TransactionPublisher;
@@ -15,12 +14,11 @@ use crate::{
};
#[derive(Clone)]
pub(crate) struct Rpc<D: Db> {
pub(crate) db: D,
pub(crate) struct Rpc {
pub(crate) rpc: SimpleRequestRpc,
}
impl<D: Db> ScannerFeed for Rpc<D> {
impl ScannerFeed for Rpc {
const NETWORK: NetworkId = NetworkId::Monero;
// Outputs aren't spendable until 10 blocks later due to the 10-block lock
// Since we assumed scanned outputs are spendable, that sets a minimum confirmation depth of 10
@@ -39,15 +37,16 @@ impl<D: Db> ScannerFeed for Rpc<D> {
&self,
) -> impl Send + Future<Output = Result<u64, Self::EphemeralError>> {
async move {
// The decoys task only indexes finalized blocks
crate::decoys::NextToIndexBlock::get(&self.db)
.ok_or_else(|| {
RpcError::InternalError("decoys task hasn't indexed any blocks yet".to_string())
})?
.checked_sub(1)
.ok_or_else(|| {
RpcError::InternalError("only the genesis block has been indexed".to_string())
})
Ok(
self
.rpc
.get_height()
.await?
.checked_sub(1)
.expect("connected to an invalid Monero RPC")
.try_into()
.unwrap(),
)
}
}
@@ -128,7 +127,7 @@ impl<D: Db> ScannerFeed for Rpc<D> {
}
}
impl<D: Db> TransactionPublisher<Transaction> for Rpc<D> {
impl TransactionPublisher<Transaction> for Rpc {
type EphemeralError = RpcError;
fn publish(