use core::marker::PhantomData; use borsh::BorshSerialize; use serai_db::{Get, DbTxn, create_db}; use primitives::{EncodableG, ReceivedOutput, Eventuality, EventualityTracker}; use crate::{ScannerFeed, KeyFor, AddressFor, OutputFor, EventualityFor}; create_db!( ScannerEventuality { // The next block to check for resolving eventualities NextToCheckForEventualitiesBlock: () -> u64, // The latest block this task has handled which was notable LatestHandledNotableBlock: () -> u64, SerializedEventualities: (key: K) -> Vec, AccumulatedOutput: (id: &[u8]) -> (), } ); pub(crate) struct EventualityDb(PhantomData); impl EventualityDb { pub(crate) fn set_next_to_check_for_eventualities_block( txn: &mut impl DbTxn, next_to_check_for_eventualities_block: u64, ) { NextToCheckForEventualitiesBlock::set(txn, &next_to_check_for_eventualities_block); } pub(crate) fn next_to_check_for_eventualities_block(getter: &impl Get) -> Option { NextToCheckForEventualitiesBlock::get(getter) } pub(crate) fn set_latest_handled_notable_block( txn: &mut impl DbTxn, latest_handled_notable_block: u64, ) { LatestHandledNotableBlock::set(txn, &latest_handled_notable_block); } pub(crate) fn latest_handled_notable_block(getter: &impl Get) -> Option { LatestHandledNotableBlock::get(getter) } pub(crate) fn set_eventualities( txn: &mut impl DbTxn, key: KeyFor, eventualities: &EventualityTracker>, ) { let mut serialized = Vec::with_capacity(eventualities.active_eventualities.len() * 128); for eventuality in eventualities.active_eventualities.values() { eventuality.write(&mut serialized).unwrap(); } SerializedEventualities::set(txn, EncodableG(key), &serialized); } pub(crate) fn eventualities( getter: &impl Get, key: KeyFor, ) -> EventualityTracker> { let serialized = SerializedEventualities::get(getter, EncodableG(key)).unwrap_or(vec![]); let mut serialized = serialized.as_slice(); let mut res = EventualityTracker::default(); while !serialized.is_empty() { let eventuality = EventualityFor::::read(&mut serialized).unwrap(); res.insert(eventuality); } res } pub(crate) fn prior_accumulated_output( getter: &impl Get, id: & as ReceivedOutput, AddressFor>>::Id, ) -> bool { AccumulatedOutput::get(getter, id.as_ref()).is_some() } pub(crate) fn accumulated_output( txn: &mut impl DbTxn, id: & as ReceivedOutput, AddressFor>>::Id, ) { AccumulatedOutput::set(txn, id.as_ref(), &()); } }