use crate::preprocessors::sized_queue::QueueByteSize;
use anyhow::Error as AnyError;
use bitcoin::Block;
use core::future::Future;
use core::pin::Pin;
pub type ProtocolFuture<'a> = Pin<Box<dyn Future<Output = Result<(), ProtocolError>> + Send + 'a>>;
pub type ProtocolPreProcessFuture<T> =
Pin<Box<dyn Future<Output = Result<T, ProtocolError>> + Send + 'static>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProtocolStage {
PreProcess,
Process,
Rollback,
Shutdown,
}
#[derive(Debug)]
pub struct ProtocolError {
stage: ProtocolStage,
source: AnyError,
}
impl ProtocolError {
pub fn new(stage: ProtocolStage, source: AnyError) -> Self {
Self { stage, source }
}
pub fn stage(&self) -> ProtocolStage {
self.stage
}
pub fn into_source(self) -> AnyError {
self.source
}
}
impl core::fmt::Display for ProtocolError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?} protocol error: {}", self.stage, self.source)
}
}
impl std::error::Error for ProtocolError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(self.source.as_ref())
}
}
pub trait BlockProtocol: Send + Sync + 'static {
type PreProcessed: QueueByteSize + Send + 'static;
fn pre_process(
&self,
block: Block,
height: u64,
) -> ProtocolPreProcessFuture<Self::PreProcessed>;
fn process<'a>(&'a mut self, data: Self::PreProcessed, height: u64) -> ProtocolFuture<'a>;
fn rollback<'a>(&'a mut self, block_height: u64) -> ProtocolFuture<'a>;
fn shutdown<'a>(&'a mut self) -> ProtocolFuture<'a>;
}